首页 > 解决方案 > 从 SSH 会话中分离命令

问题描述

我需要通过 SSH 会话在服务器上运行命令并关闭会话而不杀死服务器上的进程。如何正确实施。

服务器和客户端都是linux系统。

请注意,我无法在服务器上安装其他软件。

标签: sshprocessshremote-server

解决方案


使用特殊工具之前

  1. 理解

    当我尝试在目标上执行后台作业时,为什么 ssh 不返回。

    ssh user@host 'sleep 300 &'
    

    然后你必须点击Ctrl+C来获得你的会话。

    这是因为每个连接都包含 3个文件描述符STDIN (0)和. 当至少有一个文件描述符正在使用时,连接将保持打开状态STDOUT (1)STDERR (2)

  2. 在运行后台任务之前简单地关闭它们

    这大概是做什么nohup的。

    ssh user@host 'exec 0<&-;exec 1>&-;exec 2>&-; sleep 300 &'
    

    这将完成这项工作。

  3. 将输出重定向到静态文件

    您可以将输出存储在位于服务器端某处的文件中:

    ssh user@host 'exec 0<&-;exec 1>>/path/to/logfile;exec 2>>/path/to/errlog; sleep 300 &'
    

    >>用于将日志添加到现有文件...您可以通过添加$$date +%F...来使用 uniq 文件

    ssh user@host 'exec 0<&-;exec 1>/path/to/logfile-$$;exec 2>&1; sleep 300 &'
    

    2>&1引用后将 1>file重定向STDERR为. STDOUT_file

    ssh user@host 'exec 0<&-;exec 1>/path/to/file-$(date +%F-%T).$$;exec 2>&-;sleep 300 &'
    

    只会STDOUT存储在新文件中。

使用screen

  1. 如果screen已安装

    如果您能够访问交互式前端,您可以:

    ssh user@host screen -dmS mySleep sh -c \
              "'x=0;while [ \$x -lt 300 ];do echo \$x;x=\$((x+1));sleep 1;done'"
    

    这将启动一个后台作业,下一秒每 300 个打印 1 个 ling,然后完成。

    要重新连接,您可以

    ssh -t user@host screen -x mySleep
    

    然后Ctrl+ A,然后是d离开后台任务。

  2. screen水平安装user_

    如果你不能在服务器中安装一些东西,也许**你可以在你的$HOME目录中安装一些东西:

    (** 如果您的架构与服务器上的架构相同,这将很容易。如果不是,您甚至可以找到兼容的二进制文件或自己交叉编译。)

     $ ssh user@host
     user@host:~$ mkdir bin lib
     user@host:~$ exit
     $ scp /path/to/bin/screen user@host:~/bin
     $ ssh user@host
     user@host:~$ bin/screen
     bin/screen: error while loading shared libraries: libutempter.so.0:
               cannot open shared object file: No such file or directory
     user@host:~$ exit
     $ scp /path/to/lib/libutempter.so.0 user@host:~/lib
     $ ssh user@host
     user@host:~$ LD_LIBRARY_PATH=~/lib bin/screen
     bin/screen: /lib/x86_64-linux-gnu/libcrypt.so.1: version `XCRYPT_2.0' 
               not found (required by bin/screen)
     user@host:~$ exit
     $ scp /lib/x86_64-linux-gnu/libcrypt.so.1  user@host:~/lib
     $ ssh user@host
     user@host:~$ LD_LIBRARY_PATH=~/lib bin/screen
     Cannot make directory '/run/screen': Permission denied
     user@host:~$ mkdir $HOME/.screen
     user@host:~$ SCREENDIR=$HOME/.screen LD_LIBRARY_PATH=~/lib bin/screen
    

    最后,现在它工作了......

     $ ssh user@host SCREENDIR=\~/.screen LD_LIBRARY_PATH=\~/lib bin/screen -dmS mySleep sh -c \
              "'x=0;while [ \$x -lt 300 ];do echo \$x;x=\$((x+1));sleep 1;done'"
     $ ssh -t user@host SCREENDIR=\~/.screen LD_LIBRARY_PATH=\~/lib bin/screen -x mySleep
    

还有很多其他选择,例如tmuxbyobu...

最多创建自己的包装器...


推荐阅读