Search code examples
bashshellssh-keysopensshssh-agent

Is it possible using "su -c" with multiple commands but in one session?


I am trying run the following two command in one command.

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

I tried with many possible solutions:

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"

It seems like the first command run successfully but the second either response with Permission denied message (means it run with the current user) or cannot connect to the authentication agent (means it probably created a new session for the second command).

Error messages:

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

If I run them separately in order, it works:///

The purpose is to create a bash script with these commands with variables, something like this:

folder=/home/q12
username=q12

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

Because of the variables I can not quote the whole command because it will be sensitive to ";" and "&&".

Can anyone help me with this? Thank you!


Solution

  • You need single quotes. Otherwise the command substitution is evaluated in the current context.

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

    Edit:

    To get conditional execution of ssh-add, you can do:

    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'
    

    The argument in su -c STRING is a command string, similar to bash -c STRING. We can also nest double quotes inside single quotes.