2

I am trying to check that status of a prior command in list of commands sent to a server to change the password. When I just echo $? it works. when I store it to a variable like STATUS=$? and then echo $STATUS I get a blank line. And when I place the echo $? inside my if loop then returns something weird also. Below is the code of the ssh command for any advise on how to get this fixed.

ssh [email protected] "printf '%s\n%s' "$PASSWORD" "$PASSCONFIRM" | passwd; STATUS=$?; echo $STATUS; if (( $STATUS == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;"
Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully

Password Change Unsuccessful
bash: ((: == 0 : syntax error: operand expected (error token is "== 0 ")

2 Answers 2

2

You will need to scape the variables you want to use in the remote server.

$PASSWORD and $PASSWORDCONFIRM are fine, those are used in the local server.

$STATUS and $? you want then to be evaluated in the remote server, so you will need to scape them: STATUS=\$?, echo \$STATUS and if (( \$STATUS == 0))

Sign up to request clarification or add additional context in comments.

2 Comments

You are my hero, after posting I figure out the escaping of the echo \$STATUS and if (( \$STATUS == 0 )) but I didn't think of escaping it when storing it like STATUS=\$? Thanks so much!
I am glad it helped :)
1

First, the variable references (like $STATUS) are getting expanded by the local shell, before the command is even sent to the remote computer, let alone executed. To prevent this, you need to escape the $ (e.g. \$STATUS) so it just gets passed to the remote system rather than interpreted locally.

Second, quotes don't nest. You're trying to nest double-quotes inside a double-quoted string, and that doesn't work; you need to escape the inner double-quotes (just like the $).

You can test this by using echo instead of ssh. Normally, this is a bad way to tell what's going on with a shell command, because echo shows what the arguments look like after they've been through the shell parsing process. But in this case that's exactly what'll get sent to the remote system, so it's what you want. Here's an example:

$ PASSWORD='p4ssw0rd'
$ PASSCONFIRM='p4ssw0rd'
$ echo "printf '%s\n%s' "$PASSWORD" "$PASSCONFIRM" | passwd; STATUS=$?; echo $STATUS; if (( $STATUS == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;"
printf '%s\n%s' p4ssw0rd p4ssw0rd | passwd; STATUS=0; echo ; if ((  == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;

Note the "STATUS=0; echo ; if (( == 0 ))" -- that's because all the variable references ($? and $STATUS) got expanded locally, to 0 and "" respectively. Here's a version with appropriate escapes added:

$ echo "printf '%s\n%s' \"$PASSWORD\" \"$PASSCONFIRM\" | passwd; STATUS=\$?; echo \$STATUS; if (( \$STATUS == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;"
printf '%s\n%s' "p4ssw0rd" "p4ssw0rd" | passwd; STATUS=$?; echo $STATUS; if (( $STATUS == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;

BTW, note that I'm assuming PASSWORD and PASSCONFIRM are local, and should be expanded locally, so I didn't escape the $ on those. But there's a potential problem: if either value contains anything that's interpreted inside double-quotes, the remote shell will interpret it. So for example if your password is p4$$w0rd, the $$ will get replaced by the process ID of the remote shell. Using single-quotes around them would be better, but if they contain single-quotes, chaos will result:

$ PASSWORD="p4'\$\$w0rd"
$ echo "$PASSWORD"    # show the true password
p4'$$w0rd
$
$ # This will not work right, because of the $$:
$ echo "printf '%s\n%s' \"$PASSWORD\" \"$PASSCONFIRM\" ..."
printf '%s\n%s' "p4'$$w0rd" "p4ssw0rd" ...
$
$ # Neither will this, because of the single-quote:
$ echo "printf '%s\n%s' '$PASSWORD' '$PASSCONFIRM' ..."
printf '%s\n%s' 'p4'$$w0rd' 'p4ssw0rd' ...
$
$ # But this, while messy, will work:
$ ESCAPEDPW=${PASSWORD//\'/\'\\\'\'}
$ ESCAPEDCONFIRM=${PASSCONFIRM//\'/\'\\\'\'}
$ echo "printf '%s\n%s' '$ESCAPEDPW' '$ESCAPEDCONFIRM' ..."
printf '%s\n%s' 'p4'\''$$w0rd' 'p4ssw0rd' ...

...wait, I hear you say, that will work? Yes, and here's a demo of what that password muddle is going to do on the remote system:

$ printf '%s\n%s' 'p4'\''$$w0rd' 'p4ssw0rd'
p4'$$w0rd
p4ssw0rd

(Note that they don't match because I didn't bother to update PASSCONFIRM.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.