是否可以在一个会话中使用具有多个命令的"su -c"?



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

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消息响应(意味着它与当前用户一起运行(,要么无法连接到身份验证代理(意味着可能为第二个指令创建了一个新会话(。

错误消息:

Could not open a connection to your authentication agent.
Error connecting to agent: Permission denied

如果我按顺序分别运行它们,它会起作用:///

目的是用这些带有变量的命令创建一个bash脚本,类似于以下内容:

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

由于变量的原因,我不能引用整个命令,因为它对"以及"&amp&";。

有人能帮我吗?非常感谢。

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

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中的参数是命令字符串,类似于bash -c STRING。我们也可以在单引号中嵌套双引号。

您的第一次尝试最接近,但在双引号中,像$(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

(顺便说一句,我还在用户名周围加了双引号,因为这通常是很好的脚本卫生。引用$folder更复杂,只要它不包含任何奇怪的字符,就没有必要,所以我跳过了它。此外,{ }也没有必要,如果使用它们,}之前需要有一个;…所以我只是删除了它们。(

另一种选择是对命令的一部分进行单引号引用,对另一部分进行双引号引用(混合引号看起来很奇怪,但在shell语法中完全合法(:

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

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

最新更新