1

I have been trying to figure this one out for a while. I am trying to automate a few things. I only have rights to edit the scripts I write. I am currently using my script to call another script that I cannot edit, let's call it script.sh

I have tried:

if [[ -n $PASS ]]; then
        su -c 'echo "$PASS" | ./script.sh' &
        wait $!
    else
        ./script.sh &
        wait $!
fi
if [[ -n $PASS ]]; then
        echo "$PASS" | ./script.sh &
        wait $!
    else
        ./script.sh &
        wait $!
fi
if [[ -n $PASS ]]; then
        ./script.sh <<< $PASS &
        wait $!
    else
        ./script.sh &
        wait $!
fi

This calls a script I cannot edit:

#!/bin/bash
echo "foo: "
read PASSWORD
echo
echo "foo"
...
if [ ! -f ./config.ini ]; then
  ./script2.sh ./config.ini
fi

My issue it that script.sh then calls another script, let's say script2.sh, that cats out a config.ini file to be used later in the process. Script2.sh fails to create config.ini correctly. Specifically the command user=$(/usr/bin/who am i | cut -d ' ' -f1) fails to set the variable.

So, 3 scripts deep one command fails. But it works if run manually or if I don't echo $PASS and enter it manually. Any ideas would be greatly appreciated.

Twitch008
  • 29
  • 4
  • 1
    If you don't export a variable, it isn't in new processes' environments. – Charles Duffy Dec 16 '21 at 22:07
  • `user=$(/usr/bin/who am i | cut -d ' ' -f1)`, without the leading `$`. I don't think anything else is relevant. – chepner Dec 16 '21 at 22:07
  • BTW, why in the world are you starting something in the background and then `wait`ing for it, instead of just starting it in the foreground in the first place? – Charles Duffy Dec 16 '21 at 22:07
  • `su -c 'echo "$PASS" | ./script.sh'` isn't guaranteed to work, because just because `PASS` is set as a variable in the current script doesn't mean it's in the environment, and _definitely_ doesn't mean it'll still be in the environment after `su` is done even if it was there before. – Charles Duffy Dec 16 '21 at 22:08
  • A better replacement, if you're guaranteed bash 5.0 or later, would be `su -c "printf '%s\n' ${PASS@Q} | ./script.sh"`. If you need compatibility with earlier versions of bash, then you need to use `printf '%q'` to generate an eval-safe version of `$PASS` instead. – Charles Duffy Dec 16 '21 at 22:10
  • @Twitch008, ...and as chepner says, `$user=...anything...` will _always_ fail to assign a variable `user`, no matter what else is involved. `user=`, no leading `$`. – Charles Duffy Dec 16 '21 at 22:11
  • I added the waits in there during troubleshooting. They didn't help at all actually. I did try exporting `$PASS` but `script.sh` isn't written to read it that way. It's written to read it from STDIN and I can't change it. I can't change `script2.sh` either. – Twitch008 Dec 16 '21 at 22:14
  • 1
    (also, note that all-caps variable names are in the space used for variables that reflect or modify behavior of POSIX-defined tools; the standard reserves names with at least one lowercase character for application use -- and in this context, your script is an "application"!) – Charles Duffy Dec 16 '21 at 22:14
  • Yes, as I told you, it's not well-defined whether environment variables survive `su`; it's fairly common security policy to restrict them. That's why I provided code, in an earlier comment, that substitutes an eval-safe version of the password into the argument passed to `su` instead of requiring the child shell to read the variable from the environment. – Charles Duffy Dec 16 '21 at 22:14
  • Mind, another reason this could fail is if your program is reading direct from the TTY instead of reading the password from stdin at all! `read PASSWORD` won't do that, but if your real program were something more involved, you could end up there (compare to `read PASSWORD &2; fi`, etc). – Charles Duffy Dec 16 '21 at 22:16
  • BTW -- for reducing the number of guessing games here, `set -x` is your friend. Ideally, use it liberally -- both in the main script _and_ in your `su` commands; `su -c 'set -x; echo "$PASS" | ./script.sh'`, f/e, will log the value that's _actually_ being `echo`ed. – Charles Duffy Dec 16 '21 at 22:18
  • Does either script.sh or script2.sh (or any of the commands they run) read input? That is, do you need to provide any more input than just the password? – Gordon Davisson Dec 16 '21 at 22:55
  • After weeks of staring at this problem, I think I figured out the issue. The dev that wrote `script2.sh` made an error. So tomorrow I am going to bend the rules and try adding this to my script: `sed 's/who am i/whoami/g' script2.sh`. This is editing a script I am not allowed to edit but if it works it works. I just got it to work in my test environment at home – Twitch008 Dec 16 '21 at 23:19

0 Answers0