如何在SSH中获取最后一个后台进程的pid

时间:2017-07-10 08:05:12

标签: bash ssh

我的shell脚本以这种方式通过SSH运行:

ssh -i mycert.pem testuser@myserver.com <<SSHBLOCK
pm2 logs --lines 100 &
pid=$!
sleep 3
kill $pid
SSHBLOCK

在本地服务器上(未包装在ssh块中),脚本按预期工作。但是当我需要在远程服务器上获取日志时,$ pid只是空白。为什么是$!在上面的SSHBLOCK中使用时为空?

3 个答案:

答案 0 :(得分:2)

那是因为本地shell(用于运行[code] import os os.system('net use w: /delete') os.system('net use w: \\\\apps\\NotesFolder') [/code] 的shell)将尝试展开ssh

将此doc doc delimiter放入单引号中以避免局部变量扩展:

$!

https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Here-Documents

答案 1 :(得分:2)

当您在本地运行它时,您的shell会将$!扩展为最后一个背景pid,如您所料。但是,正如您所编写的那样,包含$!的变量正由运行ssh命令的shell扩展,而不是由远程主机扩展。

将您的heredoc视为类似于双引号:

ssh user@host "pm2 logs --lines 100 & pid=$!; sleep 3; kill $pid"

此处$!扩展到本地shell的最后一个背景pid ....

解决此问题的最简单方法可能是逃避$字符或单引号heredoc标记以避免变量扩展。还有一个选择是将整个&#34;脚本&#34;单引号:

ssh -i mycert.pem testuser@myserver.com '
  pm2 logs --lines 100 &
  pid=$!
  sleep 3
  kill $pid'

答案 2 :(得分:1)

您遇到此问题是因为您混合了本地和远程变量。

当你写:

pid=$!
sleep 3
kill $pid

您尝试读取本地客户端上使用的最后一个pid。

你应该写:

pid="\$!"
sleep 3
kill "\$pid"

获取远程值。

或者,如果您只使用远程变量,则可以引用您的heredoc:

ssh -i mycert.pem testuser@myserver.com <<'SSHBLOCK'
pm2 logs --lines 100&
pid=$!
sleep 3
kill $pid
SSHBLOCK