上述命令通过 echo 时的输出为:
# echo systemctl\ {restart,status}\ sshd\;
systemctl restart sshd; systemctl status sshd;
即使我将输出粘贴到终端,该命令仍然有效。但是当我尝试直接运行命令时,我得到:
# systemctl\ {restart,status}\ sshd\;
bash: systemctl restart sshd;: command not found...
我有两个问题..
- 这种替换和扩展的方法到底叫什么?(这样我就可以研究它并了解更多关于它以及如何正确使用它的信息)。
- 我在这里做错了什么?为什么它不起作用?
它是在 shell 中完成的Brace 扩展的一种形式。大括号扩展的想法是正确的,但在这里使用它的方式是不正确的。当你打算这样做时:
shell 解释
systemctl restart sshd;
为一个长命令并尝试运行它,但它找不到二进制文件以这种方式运行它。因为在这个阶段,shell 会在构建带有参数的完整命令之前尝试对命令行中的项目进行标记——但这还没有发生。对于此类已知的扩展值,您可以使用
eval
并且仍然是安全的,但请确定您尝试使用它扩展什么。但我宁愿使用循环代替 with
for
,而不是尝试编写单行代码或使用eval
:这称为大括号扩展(如标签所示)。
考虑在 bash 中读取和执行命令行所涉及的阶段(例如):
您要做的是从(3)影响(2)。在解析复合命令时,基于的拆分
;
处于阶段(2)。当 (3) 发生大括号扩展时,尝试创建复合命令已经太迟了。第一行
展开为 3 个令牌
然后 echo 回显最后两个令牌,看起来还可以。
同样是第二行
扩展为 2 个令牌
并且 bash 尝试寻找
systemctl restart sshd;
它找不到的可执行文件。eval systemctl\ {restart,status}\ sshd\;
您可能希望通过提防意外来开始您的黑暗之旅。