从脚本运行时,Bash脚本无法正确执行命令

时间:2017-07-15 15:36:38

标签: linux bash shell

我有一个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正确运行脚本?

1 个答案:

答案 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"