我到处寻找答案。我设置了密钥,因此 ssh 进入远程主机时不需要密码。我已为该用户设置了 sudo,这样我就可以以 root 身份运行所需的命令而无需密码。我只使用 ssh 执行远程命令几天(多么辉煌的发现!)。
一点背景知识:远程主机上运行的脚本是程序的典型启动/停止脚本。在实际程序的某个地方,会打开一个日志文件进行写入。在远程主机上,如果我以 root 身份运行脚本,则一切正常。如果我以用户身份运行它,则会收到错误:log4cplus:ERROR Unable to open file: appname.log
。这很合理,因为日志归 root 所有。
现在的情况是:我的本地主机上有一个脚本,它将通过 ssh 进入远程主机,使用 sudo 将运行该脚本。该脚本可以运行。但是,启动后,我收到与上述日志文件相同的错误。我尝试了以下操作,这些操作都成功运行了脚本,但得到了错误。我知道有些操作是不必要的,但我想涵盖我能找到的所有基础(我也尝试过使用 -t,但没有区别。我不认为会有区别,但是……):
/usr/bin/ssh username@remotehost sh -c sudo "/etc/rc3.d/S99script start"
/usr/bin/ssh username@remotehost sh -c sudo "/etc/rc3.d/S99script start"
/usr/bin/ssh username@remotehost 'sh -c sudo "/etc/rc3.d/S99script start"'
/usr/bin/ssh username@remotehost sudo /etc/rc3.d/S99script start
/usr/bin/ssh username@remotehost "sudo /etc/rc3.d/S99script start"
/usr/bin/ssh username@remotehost sudo "/etc/rc3.d/S99script start"
/usr/bin/ssh username@remotehost 'sudo "/etc/rc3.d/S99script start"'
/usr/bin/ssh username@remotehost sudo su - -c "/etc/rc3.d/S99script start"
/usr/bin/ssh username@remotehost 'sudo su - -c "/etc/rc3.d/S99script start"'
我知道我还尝试了其他方法,但我没有记录下来。不要嘲笑我尝试了所有不同的引号,我很清楚什么时候该用哪个,但我没有在尝试不同的东西时做出任何改变 :)
运行这些时我注意到,如果我对脚本名称执行 ps -ef|grep,它会显示以下内容:
[username's UID] 3070 3069 0 14:42 ? 00:00:00 bash -c /etc/rc3.d/S99script start
甚至对于我执行“sh -c sudo”的那些也是如此。它以 bash -c 运行的事实很有趣,但同样有趣的是(我认为?)它列出了用户的 UID 而不是用户名。
**添加:我还尝试在“用户名”的主目录中创建一个脚本,该脚本只执行以下任务:
sudo /etc/rc3.d/S99script start
我得到了相同的结果。
答案1
首先,更改基于密钥的身份验证,以便您以相关用户的身份登录远程系统 - 那么就无需使用 sudo(因为您已经表明该服务未以 root 身份运行,因此自动基于密钥的登录应该不存在安全问题)。
其次,查看 sshd_config(5) 中的 ForceCommand - 如果您使用的服务帐户只能执行一项操作,这将提供额外的安全性。请注意对 Match 指令的引用。
最后,sudo 在执行涉及修改系统文件的命令时可能会产生意外结果 - 这就是为什么像“sudo echo foobar >> /etc/passwd”这样的命令不能像您想象的那样工作的原因。这很可能(虽然我不能确定,除非我看到实际的脚本)是您当前情况的一个因素。按照我上面的第一个建议,您将完全绕过这个问题。:)
答案2
您把这个弄得太复杂了。 ssh -t user@host sudo /path/to/command
应该是您需要做的全部事情(没有奇怪的引用、转义、运行su
和子 shell——只是命令,就像您在手动运行时在远程端输入的命令一样)。
如果您开始使用更复杂的命令,您可能必须使用引用和转义,但对于如此简单的事情来说,这不是必需的。
请注意,-t
如果您需要输入密码,则 SSH 的标志是必需的sudo
:默认情况下,SSH 不会为远程命令会话分配 tty(sudo 会抱怨无法获取您的密码)。 -t
强制分配终端,以便sudo
可以进行交互。
在您的情况下可能不需要它,但实际上不会造成任何损害。