shell 是否可以在一个会话中使用带有多个命令的“su -c”?

e5nqia27  于 2022-11-16  发布在  Shell
关注(0)|答案(2)|浏览(396)

我尝试在一个命令中运行以下两个命令。

eval "$(ssh-agent)"
ssh add ~/.ssh/id_rsa

我尝试了许多可能的解决方案:

su username -c "{ eval $(ssh-agent -s) }; ssh-add ~/.ssh/id_rsa"
su username -c "eval $(ssh-agent -s)" ; ssh-add ~/.ssh/id_rsa
su username -c "eval $(ssh-agent -s)" && ssh-add ~/.ssh/id_rsa
su username -c "eval $(ssh-agent -s)" && "ssh-add ~/.ssh/id_rsa"

第一个命令似乎运行成功,但第二个命令要么响应Permission denied消息(表示它以当前用户身份运行),要么无法连接到身份验证代理(表示它可能为第二个命令创建了新会话)。
错误消息:
第一次
如果我按顺序分别运行它们,它将工作:///
目的是使用这些带有变量的命令创建一个bash脚本,如下所示:

folder=/home/q12
username=q12

su $username -c "{ eval $(ssh-agent -s) }; ssh-add $folder/.ssh/id_rsa"

因为变量我不能引用整个命令,因为它将是敏感的“;“和“&&"。
有人能帮我吗?谢谢!

jchrr9hc

jchrr9hc1#

您需要单引号。否则将在当前上下文中计算命令替换。

su username -c 'eval "$(ssh-agent -s)"; ssh-add ~/.ssh/id_rsa'

编辑:
要获得ssh-add的条件执行,可以执行以下操作:

su username -c 'script=$(ssh-agent -s) || exit 1; eval "$script"; ssh-add ~/.ssh/id_rsa'
# or
su username -c 'set -e; script=$(ssh-agent -s); eval "$script"; ssh-add ~/.ssh/id_rsa'

su -c STRING中的参数是一个命令 string,类似于bash -c STRING。我们也可以在单引号中嵌套双引号。

k97glaaz

k97glaaz2#

您的第一次尝试是最接近的,但是双引号内的内容(如$(ssh-agent -s))在作为参数的一部分传递给su之前 * 会由shell进行计算。ssh代理在当前用户下运行,因此其他用户不能使用它。
您需要将求值延迟到其他用户的shell。使用单引号而不是双引号可以做到这一点,* 但是 * 在实际的命令中您有$folder,您显然希望 * 您的 * shell对它求值(它不会在其他用户shell中定义),因此您 * 不 * 希望延迟对它的求值。最简单的方法是对要延迟求值的$进行转义(您的shell将删除转义符,以便其他用户的shell可以看到并计算它):

su "$username" -c "eval \$(ssh-agent -s); ssh-add $folder/.ssh/id_rsa"
#                       ^ Note the escape

(BTW,我还在用户名周围添加了双引号,因为这通常是很好的脚本卫生。引用$folder更复杂,只要它不包含任何奇怪的字符,就没有必要,所以我跳过了它。另外,{ }也没有必要,如果使用它们,在}之前需要有; ...所以我只是删除了它们。)
另一种方法是将命令的一部分用单引号引起来,另一部分用双引号引起来(混合引用看起来很奇怪,但在shell语法中完全法律的):

su "$username" -c 'eval $(ssh-agent -s);'" ssh-add $folder/.ssh/id_rsa"
#                     ^  single-quoted part ^^    double-quoted part      ^

其余的尝试都不起作用的原因是命令(;&&)之间的分隔符不在引号中,因此被 your shell视为分隔符,因此第二个命令是在您的用户ID下运行的,而不是作为su命令的一部分。

相关问题