I have my own ssh server (on raspberry pi 5, Ubuntu Server 23) but when I try to connect from my PC using key authentication (having password disabled), I get a blank screen. A blinking cursor.
However, once I enter the command eval "$(ssh-agent -s)"
and try ssh again, I successfully login after entering my passphrase. I don’t want to issue this command every time. Is that possible?
This does not occur when I have password enabled on the ssh server. Also, ideally, I want to enter my passphrase EVERYTIME I connect to my server, so ideally I don’t want it to be stored in cache or something. I want the passphrase to be a lil’ password so that other people can’t accidentally connect to my server when they use my PC.
well seems to work without tho
Just because it works, doesn’t mean it’s right.
I had a similar construct in my bashrc and forgot the quotes. It didn’t throw an error but also didn’t work. Took quite a while to find the issue. So personally, I would recommend trying to quote correctly whenever possible.
I was unclear: I did not mean to imply that it will work with it.
It’s OT, but I’ll clarify since it might be useful for people who find Bash cryptic.
Thing is, roughly speaking:
eval
will evaluate its first argument as Bash codeeval "$(any_command really)"
will run runany_command really
, take its output and then use it as first argument foreval
. So the assumption is thatany_command really
must output a valid Bash code snippet.So what
eval "$(ssh-agent -s)"
really means is, "run ssh-agent -s, collect the output and run it right here, where we are callingeval
. Compare tossh-agent -s | bash
– this would also run ssh-agent output but it would run it in a new process–a child process of the current process—so the whatever the snippet would be, it would have no way of affecting state of the parent program, which is why it’s safer.Aside: The reason we need eval in this case is that we actually need to affect state of the program: that’s the whole point. We need to set several environment variables to values that ssh-agent “knows”. Without
eval
we would have to “ask” ssh-agent separately for each value (I’m assuming it’s not even supported) and then set all these envvars using eg.export
keyword. Usingeval
we let ssh-agent dictate the whole process: which variables are going to be set to what values, with the caveat that if compromised, it could do “evil” stuff like settingPATH
to override common commands with compromised code. etc.So what’s the problem with the quotes? The Shell syntax,
foo "$(bar baz)"
will make sure that the thing between quotes isNow without quotes, Bash (as well as POSIX shell) actually have several things they can do with the output (read
man bash
for full list, but keep it for a long rainy evening). Some of it involves substituting eg. values like*
with matching filenames, some of it may involve actually splitting the output to separate arguments based on spaces or other special characters (which can even be different characters depending on current state, seeIFS
and the likes).You can see the difference, if you run eg.
printf '[%s]\n'
instead ofeval
. This printf syntax will simply print all of following arguments on a separate line, adding braces before and after. You can compare(both of these commands should be safe as long as
ssh-agent
is not compromised and as long I have not made any terrible typo)