我有一个shell脚本如下
#!/bin/bash
USER=someuser
HOSTNAMEORIP=somehostname
SCRIPT="/etc/rc.d/netif restart && /etc/rc.d/routing restart"
su -c "ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT}" -s /bin/sh someotheruser
如果我登录到机器并运行"/etc/rc.d/netif restart && /etc/rc.d/routing restart"
它就可以了。但是如果我运行上面的整个脚本,我会得到sh: 1: /etc/rc.d/routing: not found
,好像它没有处理脚本部分一样。我甚至可以在没有像这样的用户的情况下使用上面的脚本
#!/bin/bash
USER=someuser
HOSTNAMEORIP=somehostname
SCRIPT="/etc/rc.d/netif restart && /etc/rc.d/routing restart"
ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT}
它可以工作,但我需要使用su -c <command> -s /bin/sh user
,因为另一个应用程序正在调用脚本,并且相关的用户是唯一一个使用ssh-key登录/没有密码的用户。
如何在此用例中使su -c "ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT}" -s /bin/sh someotheruser
正确运行脚本?
答案 0 :(得分:5)
让我们完成它。这个命令:
su -c "ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT}" -s /bin/sh someotheruser
将执行此字符串作为shell命令:
ssh -l someuser somehostname /etc/rc.d/netif restart && /etc/rc.d/routing restart
这显然是错误的,并且会因同样的错误而失败。
要修复它,让我们修复命令并向后工作。你应该执行
ssh -l someuser somehostname '/etc/rc.d/netif restart && /etc/rc.d/routing restart'
因此,您可以像这样更新脚本:
#!/bin/bash
USER=someuser
HOSTNAMEORIP=somehostname
SCRIPT="/etc/rc.d/netif restart && /etc/rc.d/routing restart"
su -c "ssh -l ${USER} ${HOSTNAMEORIP} '${SCRIPT}'" -s /bin/sh someotheruser
# ^--- ^---
请注意,这取决于$SCRIPT
不包含嵌入式单引号的事实。如果您不知道,或者您不知道,可以在嵌入字符串中使用$(printf "%q" "$SCRIPT")
而不是'$SCRIPT'
来使bash自动转义它。
或者您可以切换到sudo
。由于它使用安全且健壮的execve(2)
语义而不是system(3)
语义,因此您不必嵌套转义:
sudo -u someotheruser ssh -l "$USER" "$HOSTNAMEORIP" "$SCRIPT"