我使用的bash命令:
1.
$ ssh user@myserver.com ps -aux|grep -v \"grep\"|grep "/srv/adih/server/app.js"|awk '{print $2}'
6373
2。
$ ssh user@myserver.com echo $(ps -aux|grep -v \"grep\"|grep "/srv/adih/server/app.js"|awk '{print $2}')
8630
第一个结果是正确的结果,第二个结果将改变我执行它的回波时间。但我不知道为什么他们不同。
我在做什么?
我的工作站资源非常有限,所以我使用远程机器来运行我的节点应用程序。我使用ssh user@remotebox.com运行它" cd / applocation&&咕噜声"在调试模式下。当我命令CTRL+C
时,grunt任务停止但应用程序仍在调试模式下运行。我只是想要杀死它,我需要先得到pid。
答案 0 :(得分:3)
在ssh
运行之前,命令替换由本地shell执行。
如果您的本地系统名称为here
且遥控器为there
,
ssh there uname -n
将打印there
而
ssh there echo $(uname -n) # should have proper quoting, too
将在本地运行uname -n
,然后将展开的命令行echo here
发送到there
以执行。
另外,echo $(command)
是useless use of echo
,除非您在打印之前明确要求shell在command
的输出上执行通配符扩展和空白标记化。
此外,grep x | awk { y }
是useless use of grep
;它可以而且可能应该重构为awk '/x/ { y }'
- 当然,在这里你重新发明pidof
以便更好地使用它。
ssh user@myserver.com pidof /srv/adih/server/app.js
如果要在本地捕获打印的PID,则其语法为
pid=$(ssh user@myserver.com pidof /srv/adih/server/app.js)
当然,如果你只需要杀死它,那就是
ssh user@myserver.com pkill /srv/adih/server/app.js
答案 1 :(得分:2)
简答:在本地计算机上运行$(ps ... )
命令替换,然后将其输出(以及echo
命令)发送到远程计算机。从本质上讲,它正在运行ssh user@myserver.com echo 8630
。
你的第一个命令也可能没有达到预期的效果;管道在本地计算机上进行解释,因此它正在运行ssh user@myserver.com ps -aux
,将输出汇总到本地计算机上的grep
,将管道连接到另一台{{1}在本地计算机等等我猜测你想要在远程计算机上运行整个事情,以便可以在远程计算机上使用结果来终止进程。
答案很长:在shell中解析和执行的命令有点令人困惑;在混合中使用grep
命令,事情变得更加复杂。基本上,发生的是本地shell解析命令行,包括将其拆分为单独的命令(由管道ssh
等分隔),以及扩展;
和$(command)
替换(除非他们是单引号)。然后删除引号和转义(它们已经完成了它们的工作)并将结果作为参数传递给各种命令(例如$variable
)。 ssh
获取其参数,将所有看起来像远程命令的部分的部分与它们之间的空格一起粘贴,然后将它们发送到远程计算机上的shell ,再次执行此过程
这意味着如果您希望远程shell而不是本地shell对它们进行解析/操作,则必须引用和/或转义ssh
和$
之类的内容。并且引用不会嵌套,因此在整个事物周围放置引号可能无法按预期方式工作(例如,如果您不小心,那awk命令中的|
可能会在本地扩展计算机,即使它看起来像是单引号。)
当事情变得如此混乱时,最简单的方法是将远程命令作为here-document而不是$2
命令的参数传递。但是你需要在here-document分隔符周围引用以保持各种ssh
扩展不被本地shell完成。像这样:
$
注意:请小心缩进远程命令,因为文本将逐字地发送到远程计算机。如果您使用制表符进行缩进,则可以使用ssh user@myserver.com <<'EOF'
echo $(ps -aux|grep -v "grep"|grep "/srv/adih/server/app.js"|awk '{print $2}')
EOF
作为此处的文档分隔符(例如<<-
),然后删除主要标签。
<<-'EOF'
,因为grep
可以完成整个工作。从结果(awk
)中排除搜索命令也是不必要的,因为&#34; /&#34;模式中的字符需要转义,这意味着它不会匹配自己。所以你可以简化管道:
grep -v grep
现在,我一直在假设实际目标是ps -aux | awk '/\/srv\/adih\/server\/app.js/ {print $2}'
相关的pid,kill
就在那里进行测试。如果是这种情况,那么实际的命令就会出现:
echo
如果这不对,那么整个ssh user@myserver.com <<'EOF'
kill $(ps -aux | awk '/\/srv\/adih\/server\/app.js/ {print $2}')
EOF
事情最好完全跳过。没有理由捕获管道的输出然后echo $( )
它,只需运行它并让它直接输出。
如果echo
(或类似的东西)可用,那么使用它会更简单。