why can't I connect to my ssh server UNLESS I enter eval "$(ssh-agent -s)" first?
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.
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 code
eval "$(any_command really)" will run run any_command really, take its output and then use it as first argument for eval. So the assumption is that any_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 calling eval. Compare to ssh-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. Using eval 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 setting PATH 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 is
kept verbatim
treated as a single argument, even if it contains newlines (with some ugly exceptions to this regarding the final newline)
Now 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, see IFS and the likes).
You can see the difference, if you run eg. printf '[%s]\n' instead of eval. This printf syntax will simply print all of following arguments on a separate line, adding braces before and after. You can compare
printf '|%s|\n' $(ssh-agent -s) # printf will probably receive multiple extra arguments
printf '|%s|\n' "$(ssh-agent -s)" # printf will receive just one extra argument (and print it as specified)
(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)