首页 文章

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

提问于
浏览
274

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

我怎样才能防止这种情况发生?

20 回答

  • 160

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

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

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

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

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

  • 4

    正如其他人所指出的那样,要在后台运行进程以便可以断开与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(堆栈溢出问题)存储库中的GitHub上可用,作为packages子目录中的文件 daemonize-1.10.tgz .

  • 33

    我也会去屏幕程序(我知道其他人的答案是屏幕,但这是一个完成)

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

    screen will background your process without losing interactive control to it
    

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

  • 288

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

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

  • 36

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

    sudo apt-get install tmux

    用法:

    tmux运行你想要的命令

    要重命名会话:

    按Ctrl B然后$ set Name

    退出会话:

    按Ctrl B,然后按D.

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

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

    tmux附加session_name

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

  • 1

    还有开源libslack包的daemon命令 .

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

  • 5

    查看“nohup”程序 .

  • 3

    守护进程? 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
    

    在那里你去,产生什么 . <(:)通过进程替换打开一个匿名管道,它会消失,但管道会因为你有一个句柄而四处乱窜 . 我通常做一个 sleep 1 而不是 : ,因为它略显活泼,我会得到一个"file busy"错误 - 如果运行了一个真正的命令就不会发生(例如, command true

    “heredoc采购”:

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

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

  • 16

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

  • 2

    接受的答案建议使用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
    
  • 2

    当会话关闭时,进程收到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.
    
  • 11

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

    您需要了解的基本命令:

    开始屏幕

    屏幕


    c 重新下一个屏幕

    ctrl a c


    要移动到您创建的 n ext屏幕

    ctrl a n


    d etach

    ctrl a d


    在工作期间关闭你的腻子 . 下次当你通过putty类型登录时

    screen -r

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

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

  • 0

    在systemd / Linux上,systemd-run是一个很好的工具来启动与会话无关的进程 . 愤世嫉俗的人看什么都不顺眼

  • 4

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

  • 1

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

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

  • 76

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

  • 4

    就个人而言,我喜欢'批处理'命令 .

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

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

  • 2
    nohup blah &
    

    用你的进程名称替换等等!

  • 1

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

    # ((mycommand &)&)
    

    例如:

    # ((sleep 30 &)&)
    # exit
    

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

    # ps aux | grep sleep
    

    将显示 sleep 30 仍在运行 .

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

    我更喜欢这种"set it and forget it"方法,不需要处理 nohupscreen ,tmux,I / O重定向或任何这些东西 .

相关问题