为什么我的 Python 后台进程在 SSH 会话终止时结束?

nev*_*gqs 22 bash ssh python background-process

我有一个 bash 脚本,它启动一个 python3 脚本(让我们称之为startup.sh),关键行:

nohup python3 -u <script> &
Run Code Online (Sandbox Code Playgroud)

当我ssh直接进入并调用此脚本时,python脚本在我退出后继续在后台运行。但是,当我运行此命令时:

ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
Run Code Online (Sandbox Code Playgroud)

该过程ssh在完成运行后立即结束并关闭会话。

两者有什么区别?

编辑:python 脚本通过 Bottle 运行 Web 服务。

EDIT2:我也尝试创建一个调用startup.sh和运行的初始化脚本ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "sudo service start <servicename>",但得到了相同的行为。

EDIT3:也许是脚本中的其他内容。这是脚本的大部分内容:

chmod 700 ${key_loc}

echo "INFO: Syncing files."
rsync -azP -e "ssh -i ${key_loc} -o StrictHostKeyChecking=no" ${source_client_loc} ${remote_user}@${remote_hostname}:${destination_client_loc}

echo "INFO: Running startup script."
ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart"
Run Code Online (Sandbox Code Playgroud)

EDIT4:当我在最后一行睡眠时运行:

ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart; sleep 1"

echo "Finished"
Run Code Online (Sandbox Code Playgroud)

它永远不会到达echo "Finished",并且我看到了 Bottle 服务器消息,这是我以前从未见过的:

Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
Run Code Online (Sandbox Code Playgroud)

如果我手动 SSH 进入并自己终止进程,我会看到“已完成”。

EDIT5:使用 EDIT4,如果我向任何端点发出请求,我会返回一个页面,但 Bottle 会出错:

Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.


----------------------------------------
Exception happened during processing of request from ('<IP>', 55104)
Run Code Online (Sandbox Code Playgroud)

jll*_*gre 13

我会将命令与其标准输入/输出和错误流断开连接:

nohup python3 -u <script> </dev/null >/dev/null 2>&1 &  
Run Code Online (Sandbox Code Playgroud)

ssh需要一个没有更多输出并且不需要更多输入的指标。将其他东西作为输入并重定向输出意味着ssh可以安全地退出,因为输入/输出不是来自或去往终端。这意味着输入必须来自其他地方,而输出(STDOUT 和 STDERR)应该去其他地方。

</dev/null部件指定/dev/null为 的输入<script>。为什么这在这里很有用:

将 /dev/null 重定向到 stdin 将立即为来自该进程的任何读取调用提供 EOF。这对于将进程与 tty 分离通常很有用(这样的进程称为守护进程)。例如,当通过 ssh 远程启动后台进程时,您必须重定向 stdin 以防止进程等待本地输入。 /sf/ask/1396868231/#19955475

或者,只要当前ssh会话不需要保持打开状态,从另一个输入源重定向应该是相对安全的。

与所述>/dev/null部分壳体重定向标准输出到的/ dev / null的基本上丢弃它。>/path/to/file也会起作用。

最后一部分2>&1是将 STDERR 重定向到 STDOUT。

一个程序有三个标准的输入和输出源。标准输入通常来自键盘,如果它是一个交互式程序,或者来自另一个程序,如果它正在处理另一个程序的输出。程序通常打印到标准输出,有时打印到标准错误。这三个文件描述符(您可以将它们视为“数据管道”)通常称为 STDIN、STDOUT 和 STDERR。

有时他们没有名字,他们有编号!它们的内置编号依次为 0、1 和 2。默认情况下,如果您没有明确命名或排名第一,那么您就是在谈论 STDOUT。

鉴于该上下文,您可以看到上面的命令将标准输出重定向到 /dev/null,这是您可以转储任何您不想要的(通常称为位桶)的地方,然后将标准错误重定向到标准输出(执行此操作时,您必须在目的地前面放一个 &)。

因此,简短的解释是“该命令的所有输出都应该被推入黑洞。” 这是使程序真正安静的一种好方法!
> /dev/null 2>&1 是什么意思?| Xaprb


归档时间:

查看次数:

27236 次

最近记录:

8 年,5 月 前