在Linux中,如何在关闭SSH客户端后阻止后台进程停止

时间:2008-11-12 19:19:54

标签: linux process ssh background-process

我正在通过SSH(Putty)在linux机器上工作。 我需要让一个进程在夜间运行,所以我想我可以通过在后台启动进程(在命令末尾有一个&符号)并将stdout重定向到文件来做到这一点。 令我惊讶的是,这不起作用。一旦我关闭Putty窗口,该过程就会停止。

如何防止这种情况发生?

20 个答案:

答案 0 :(得分:294)

查看“nohup”计划。

答案 1 :(得分:163)

我建议使用GNU Screen。它允许您在所有进程继续运行时断开与服务器的连接。在我知道它存在之前,我不知道我是如何在没有它的情况下生活的。

答案 2 :(得分:78)

当会话关闭时,进程收到SIGHUP信号,该信号显然没有捕获。您可以在启动进程时使用nohup命令,也可以在启动进程后使用bash内置命令disown -h来防止这种情况发生:

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.

答案 3 :(得分:37)

守护进程? nohup的?屏幕? (tmux ftw,屏幕是垃圾; - )

完成其他应用从开始以来所做的事情 - 双叉。

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

砰!完成:-)我在所有类型的应用程序和许多旧机器上使用过无数次。您可以结合重定向等等来打开您与流程之间的私人渠道。

创建为coproc.sh:

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

然后

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

然后你去,产生什么。 &lt;(:)通过进程替换打开一个匿名管道,它会消失,但管道会因为你有一个句柄而四处乱窜。我通常使用sleep 1代替:,因为它略显活泼,而且我会收到“文件繁忙”错误 - 如果运行了真正的命令,则永远不会发生(例如command true

“heredoc sourcing”:

. /dev/stdin <<EOF
[...]
EOF

这适用于我曾尝试过的每一个shell,包括busybox / etc(initramfs)。我以前从未见过它,我在刺激时独立发现它,谁知道源可以接受args?但是,如果存在这样的事情,它通常可以作为一种更易于管理的评估形式。

答案 4 :(得分:33)

nohup blah &

将您的流程名称替换为blah!

答案 5 :(得分:17)

就个人而言,我喜欢'batch'命令。

$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D

将其填入后台,然后将结果邮寄给您。这是cron的一部分。

答案 6 :(得分:11)

正如其他人所指出的那样,要在后台运行进程以便可以断开与SSH会话的连接,您需要让后台进程正确地与其控制终端取消关联 - 这是SSH会话的伪tty使用

您可以在书籍中找到有关守护进程的信息,例如Stevens的“高级网络程序,第1卷,第3版”或Rochkind的“高级Unix编程”。

我最近(在过去的几年里)不得不处理一个没有正确守护自己的顽固计划。我最终通过创建一个通用的守护程序处理它 - 类似于nohup但有更多控件可用。

Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
  -V          print version and exit
  -a          output files in append mode (O_APPEND)
  -b          both output and error go to output file
  -c          create output files (O_CREAT)
  -d dir      change to given directory
  -e file     error file (standard error - /dev/null)
  -h          print help and exit
  -i file     input file (standard input - /dev/null)
  -k fd-list  keep file descriptors listed open
  -m umask    set umask (octal)
  -o file     output file (standard output - /dev/null)
  -s sig-list ignore signal numbers
  -t          truncate output files (O_TRUNC)
  -p          print daemon PID on original stdout
  -x          output files must be new (O_EXCL)

对于不使用GNU getopt()函数的系统,双破折号是可选的;在Linux等上是必要的(或者你必须在环境中指定POSIXLY_CORRECT)。因为双破折号在任何地方都可以使用,所以最好使用它。

如果您想要daemonize的来源,您仍然可以与我联系(gmail dot com的名字点姓氏)。

但是,现在(终于)可以在我的SOQ(Stack。)的GitHub上使用该代码 溢出问题)存储库作为文件daemonize-1.10.tgz packages 子目录。

答案 7 :(得分:5)

Nohup允许客户端进程在父进程被终止时被杀死,以便在您注销时进行参数处理。更好的还是使用:

nohup /bin/sh -c "echo \$\$ > $pidfile; exec $FOO_BIN $FOO_CONFIG  " > /dev/null

Nohup使您开始免受终止的过程,当您退出时,您的SSH会话及其子进程将被终止。我给出的命令为您提供了一种方法,您可以将应用程序的pid存储在pid文件中,以便以后可以正确地删除它,并允许该进程在您注销后运行。

答案 8 :(得分:5)

如果您使用screen以root身份运行进程,请注意权限提升攻击的可能性。如果您自己的帐户以某种方式受到损害,将有一种直接的方式来接管整个服务器。

如果需要定期运行此过程并且您在服务器上有足够的访问权限,则更好的选择是使用cron运行该作业。你也可以使用init.d(超级守护进程)在后台启动你的进程,它可以在完成后立即终止。

答案 9 :(得分:5)

如果您想将详细信息记录到文件中,

nohup非常好。但是当它转到后台时,如果你的脚本要求,你就无法给它一个密码。我想你必须尝试screen。它是一个可以在你的Linux发行版上使用yum安装的实用程序,例如在CentOS yum install screen上,然后通过putty或其他软件在你的shell类型screen中访问你的服务器。它将在putty中打开screen [0]。做你的工作。您可以在同一个putty会话中创建更多屏幕[1],屏幕[2]等。

您需要了解的基本命令:

开始画面

屏幕


c 重新设置下一个屏幕

CTRL + A + C


要移至您创建的 n ext屏幕

CTRL + A + N


d etach

CTRL + A + d


在工作期间关闭你的腻子。下次通过putty type

登录时

screen -r

要重新连接到屏幕,您可以在屏幕上看到您的进程仍在运行。并退出屏幕,输入#exit。

有关详细信息,请参阅man screen

答案 10 :(得分:5)

在基于Debian的系统上(在远程计算机上) 安装:

  

sudo apt-get install tmux

用法:

  

TMUX

     

运行您想要的命令

重命名会话:

  

Ctrl + B 然后 $

     

设置名称

退出会话:

  

Ctrl + B 然后 D

(这离开了tmux会话)。然后,您可以注销SSH。

当您需要再次返回/检查时,启动SSH,然后输入

  

tmux attach session_name

它会带你回到你的tmux会话。

答案 11 :(得分:5)

对于大多数进程,您可以使用这个旧的Linux命令行技巧进行伪守护:

# ((mycommand &)&)

例如:

# ((sleep 30 &)&)
# exit

然后启动一个新的终端窗口并:

# ps aux | grep sleep

将显示sleep 30仍在运行。

你所做的是作为一个孩子的孩子开始这个过程,当你退出时,通常会触发进程退出的nohup命令不会级联到大孩子,离开它作为一个孤儿进程,仍在运行。

我更喜欢这种“设置并忘记它”的方法,无需处理nohupscreen,tmux,I / O重定向或其他任何内容。

答案 12 :(得分:4)

使用屏幕。它使用起来非常简单,并且像终端的vnc一样工作。 http://www.bangmoney.org/presentations/screen.html

答案 13 :(得分:2)

如果您也愿意运行X应用程序 - 请将xpra与“screen”一起使用。

答案 14 :(得分:2)

我也会选择屏幕程序(我知道其他一些答案是屏幕,但这是完成)

不仅&amp;,ctrl + z bg disown,nohup等等这一事实可能会给你一个令人讨厌的惊喜,当你注销工作时仍会被杀死(我不知道为什么,但它确实发生在我身上,而且它没有打扰它是因为我切换到使用屏幕,但我认为anthonyrisinger解决方案,因为双重分叉会解决这个问题),屏幕有一个主要优势而不仅仅是背面接地:

screen will background your process without losing interactive control to it

和btw,这是一个我永远不会问的问题:) ...我在任何unix中做任何事情的开始使用屏幕...我(几乎)从不在unix / linux shell中工作没有首先开始屏幕...我现在应该停止,或者我将开始无休止地展示什么是好的屏幕以及可以为你做什么...自己查看,这是值得的;)

答案 15 :(得分:2)

还有开源libslack软件包的daemon命令。

daemon是可配置的,并且关心所有繁琐的守护进程,例如自动重启,日志记录或pidfile处理。

答案 16 :(得分:2)

将此字符串附加到您的命令:&gt;&amp; - 2&gt;&amp; - &lt;&amp; - &amp;。 &gt;&amp; - 表示关闭标准输出。 2&gt;&amp; - 表示关闭stderr。 &lt;&amp; - 表示关闭stdin。 &安培;意味着在后台运行。这也可以通过ssh以编程方式启动作业:

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$

答案 17 :(得分:1)

我使用了screen命令。此链接详细说明了如何执行此操作

https://www.rackaid.com/blog/linux-screen-tutorial-and-how-to/#starting

答案 18 :(得分:1)

接受的答案建议使用 nohup 。我宁愿建议使用pm2。在 nohup 上使用 pm2 有许多优点,例如保持应用程序处于活动状态,维护应用程序的日志文件以及更多其他功能。有关详细信息check this out

要安装 pm2 ,您需要下载 npm 。对于基于Debian的系统

sudo apt-get install npm

和Redhat

sudo yum install npm

或者您可以关注these instruction。 安装 npm 后,使用它来安装 pm2

npm install pm2@latest -g

完成后,您可以通过

开始申请
$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

对于过程监控,请使用以下命令:

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

使用应用名称或流程ID管理流程或一起管理所有流程:

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

日志文件可以在

中找到
$HOME/.pm2/logs #contain all applications logs

二进制可执行文件也可以使用pm2运行。你必须改变jason文件。将"exec_interpreter" : "node"更改为"exec_interpreter" : "none".(请参阅attributes section)。

#include <stdio.h>
#include <unistd.h>  //No standard C library
int main(void)
{
    printf("Hello World\n");
    sleep (100);
    printf("Hello World\n");

    return 0;
}

编译上面的代码

gcc -o hello hello.c  

并在后台运行np2

pm2 start ./hello

答案 19 :(得分:1)

在systemd / Linux上,systemd-run是启动与会话无关的进程的好工具。仇恨者会讨厌