非交互运行时bash测试错误结果

杰拉德·施耐德

当需要重新启动时,我正在尝试通过脚本重新启动许多 Ubuntu 服务器。

当我使用测试作为非交互式命令执行 bash 时,我得到的结果是不需要重新启动,即使文件/var/run/reboot-required存在。

[email protected]:~$ ssh server02 bash -c 'test -f /var/run/reboot-required && echo sudo reboot || echo "$(hostname): no reboot required"'
server02: no reboot required

当我通过 SSH 登录到同一台服务器并手动运行我的测试时,我得到了正确的结果,sudo reboot.

[email protected]:~$ ssh server02
Last login: Tue Jun 14 08:03:00 2022 from 146.140.16.1
[email protected]:~$ test -f /var/run/reboot-required && echo sudo reboot || echo "$(hostname): no reboot required"
sudo reboot
[email protected]:~$ bash -c 'test -f /var/run/reboot-required && echo sudo reboot || echo "$(hostname): no reboot required"'
sudo reboot

我需要改变什么才能得到正确的结果?

伊尔卡丘

我很确定这是因为 SSH 将命令传递到远程端的方式,它通过连接它获得的所有参数、用空格连接它们并让远程上的 shell 解析并执行它来做到这一点。

考虑一下ssh somehost ls -l /etc/passwd与 相同的工作ssh somehost 'ls -l /etc/passwd',后者不会给出关于不存在的奇怪命名命令的错误,这与'ls -l /etc/passwd'直接在 shell 命令行上运行时不同。

所以,

ssh somehost bash -c 'test whatever || echo no'

变成命令行

bash -c test whatever || echo no

Bash 在哪里运行命令test$0设置为whatever. test没有参数失败,所以|| echo运行。您也可以尝试类似的方法ssh somehost bash -c 'ls -l /etc/passwd',它应该只ls在您的远程主目录中运行。

因此,请尝试不使用中间外壳:

ssh server02 'test -f /etc/passwd && echo passwd exists || echo "$(hostname): passwd does not exist"'

或者你可以做类似的事情

ssh server02 'bash -c "test -f /etc/passwd && echo yes || echo \"\$(hostname): no\"'

但是如果你想嵌套另一个带引号的字符串并确保它是运行你拥有的任何扩展的最里面的 shell,那么那里的引用确实会变得很糟糕。这并不重要,$(hostname)因为它会从遥控器上的任一 shell 给出相同的结果,但在更一般的情况下,引用地狱就在那里。在这样的复杂情况下,只需在遥控器上创建一个文件并从那里运行脚本会容易得多。

这与带引号的 ssh 命令中的问题基本相同

另请参阅通过 SSH 执行 `sh -c` 脚本(安全和理智地传递参数)以了解其他传递复杂命令的解决方案,以及如何在不知道远程用户的登录 shell 的情况下通过 ssh 执行任意简单命令?对于涉及可能未知的远程登录 shell 的罕见情况。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected]mail.com 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章