代码之家  ›  专栏  ›  技术社区  ›  GetFree

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

  •  277
  • GetFree  · 技术社区  · 17 年前

    我正在通过SSH(Putty)在Linux机器上工作。我需要让一个进程在夜间运行,所以我想我可以在后台启动该进程(在命令末尾使用一个符号)并将stdout重定向到一个文件。

    令我惊讶的是,这不起作用。我一关闭腻子窗口,过程就停止了。

    20 回复  |  直到 7 年前
        1
  •  306
  •   JesperE    17 年前

    请查看“ nohup “计划。

        2
  •  168
  •   gpojd    17 年前
        3
  •  82
  •   Robert Gamble    17 年前

    当会话关闭时,进程接收到SIGHUP信号,但显然没有捕获到该信号。你可以使用 nohup 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.
    
        4
  •  41
  •   MackM    8 年前

    daemonize?诺胡普?屏幕(tmux ftw,屏幕是垃圾;-)

    只要做其他应用程序从一开始就做过的事情——双叉。

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

    猛敲完成:-)我已经在所有类型的应用程序和许多旧机器上使用过无数次了。您可以结合重定向等功能,在您和流程之间打开一个专用通道。

    #!/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
    

    你就这样,生什么就生什么。这个<(:)通过进程替换打开一个匿名管道,该管道将终止,但由于您有一个句柄,所以管道会粘住。我通常做一个 sleep 1 而不是 : command true )

    “heredoc采购”:

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

        5
  •  36
  •   Nathan Fellman    17 年前
    nohup blah &
    

    用你的流程名称代替废话!

        6
  •  17
  •   Will Hartung    17 年前

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

    这会将其填充到后台,然后将结果发送给您。它是cron的一部分。

        7
  •  11
  •   Jonathan Leffler    8 年前

    正如其他人所指出的,要在后台运行进程以便可以断开与SSH会话的连接,您需要让后台进程正确地将自己与其控制终端(SSH会话使用的伪tty)断开关联。

    您可以在Stevens的《高级网络程序,第1卷,第3版Edn》或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)。由于双破折号在任何地方都有效,因此最好使用它。

    如果你想知道我的信息来源,你仍然可以联系我(在gmail.com上的firstname.lastname) daemonize .

    但是,该代码现在(最终)在我的 SOQ (堆叠 溢出问题)存储库作为文件 daemonize-1.10.tgz packages 子目录。

        8
  •  10
  •   Paul Roub jim    10 年前

    # ((mycommand &)&)
    

    例如:

    # ((sleep 30 &)&)
    # exit
    

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

    # ps aux | grep sleep
    

    sleep 30 它仍在运行。

    您所做的是作为子进程的子进程启动该进程,当您退出时 nohup

    我更喜欢这种“设置它,忘记它”的方法,不需要处理 诺胡普 , screen

        9
  •  7
  •   Community Mohan Dere    6 年前

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

    用法:

    tmux

    运行所需的命令

    Ctrl+B 然后 $

    要退出会话,请执行以下操作:

    Ctrl+B 然后 D

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

    tmux附加会话\u名称

        10
  •  5
  •   Dana the Sane    17 年前

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

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

        11
  •  5
  •   Community Mohan Dere    6 年前

    nohup screen . 它是一个实用工具,您可以使用yum在linux发行版上安装,例如在CentOS上 yum install screen 然后通过putty或其他软件访问您的服务器,在您的shell类型中 . 它将在腻子中打开屏幕[0]。做好你的工作。您可以在同一putty会话中创建更多屏幕[1],屏幕[2]等。

    您需要了解的基本命令:

    启动屏幕

    屏幕


    C 创建下一屏幕

    ctrl+a+c


    迁往 N 您创建的外部屏幕

    ctrl+a+n


    D 伊塔赫


    在工作中关闭你的油灰。下次您通过putty类型登录时

    屏幕-r

    man screen .

        12
  •  5
  •   Naveen Vijay    9 年前

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

    Nohup使您启动的进程不受终止的影响,您的SSH会话及其子进程在您注销时被终止。我给出的命令提供了一种方法,可以将应用程序的pid存储在pid文件中,以便稍后正确地将其杀死,并允许进程在注销后运行。

        13
  •  3
  •   Deon    17 年前

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

        14
  •  2
  •   Alexey Shurygin    14 年前

    如果您也愿意运行X应用程序,请使用 xpra 与“屏幕”一起使用。

        15
  •  2
  •   THESorcerer    14 年前

    不仅如此;,ctrl+z bg disown、nohup等可能会给你们一个令人不快的惊喜,当你们注销时,工作仍然会被终止(我不知道为什么,但它确实发生在我身上,它并没有打扰到我,因为我切换到使用屏幕,但我想anthonyrisinger解决方案作为双分叉会解决这个问题),屏幕也有一个 专业 与刚接地相比的优势:

    screen will background your process without losing interactive control to it
    

    顺便说一句,这是一个我从一开始就不会问的问题:)。。。我从一开始就在任何unix中使用screen。。。我(几乎)从未在unix/linux shell中工作过,除非先启动screen。。。我现在应该停下来,否则我将开始一个无休止的介绍什么是好屏幕,什么可以为你做。。。你自己去查,这是值得的;)

        16
  •  2
  •   janv    14 年前

    还有 daemon 开源libslack包的命令。

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

        17
  •  2
  •   tbc0 Sourcegeek    13 年前

    将此字符串附加到命令:>&-2>&-<&-&&燃气轮机&-意思是接近标准。2>&-意味着接近标准<&-表示接近标准&意思是在后台运行。这也可以通过ssh以编程方式启动作业:

    $ ssh myhost 'sleep 30 >&- 2>&- <&- &'
    # ssh returns right away, and your sleep job is running remotely
    $
    
        18
  •  1
  •   Shravan Ramamurthy    10 年前

    我使用屏幕命令。此链接详细介绍了如何执行此操作

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

        19
  •  1
  •   haccks    9 年前

    接受答案建议使用 pm2 . 使用 诺胡普 具有许多优点,如保持应用程序的活动性、维护应用程序的日志文件以及更多其他功能。更多细节 check this out .

    安装 你需要下载 npm . 基于Debian的系统

    sudo apt-get install npm
    

    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
    
        20
  •  0
  •   tripleee    5 年前

    systemd-run 是启动会话无关进程的好工具。