2

I'm trying to write something that stores an API access token in a bash variable, so I'm modelling it on ssh-agent, where you use eval.

ssh-agent

If you run ssh-agent by itself, it outputs something like the following:

SSH_AUTH_SOCK=/tmp/ssh-XXXXXXXXXXXX/agent.NNNNN; export SSH_AUTH_SOCK;
SSH_AGENT_PID=NNNNN; export SSH_AGENT_PID;
echo Agent pid NNNNN;

And if you run it with eval $(ssh-agent), it outputs:

Agent pid NNNNN

...and the eval results in the environment variables being set in your current shell.

my script

The end of my script looks like this ($JSON came from some earlier curl command):

cat <<EOF
API_ACCESS_TOKEN=$(echo $JSON | jq '.access_token')
API_EXPIRES_AT=$(echo $JSON | jq '.expires_at')
export API_ACCESS_TOKEN API_EXPIRES_AT
echo OK
EOF

When I run it with eval $(./auth), it's correctly setting $API_ACCESS_TOKEN and $API_EXPIRES_AT (so the eval works), but it's not printing "OK".

What am I doing wrong?

2 Answers2

3

Have a look at that output from ssh-agent again. You are missing the terminating ; after each command.

With these, the script will do what you want.

Without the semicolons, the shell will execute the commands in the string (the here-document) as one command with the newlines removed.

Kusalananda
  • 333,661
3

This, too, seems a word-splitting issue. The script outputs (essentially) this:

VAR=foo
export VAR
echo OK

But since you used an unquoted command substitution, it gets split, and given to eval as distinct words, as if you entered:

eval VAR=foo export VAR echo OK

After that, Bash's declare shows that echo and OK are exported, though not set:

$ declare -p echo
declare -x echo

So you'd need to either quote the command substition (eval "$(./auth)") or put the semicolons in there as ssh-agent does.

ilkkachu
  • 138,973