0

Sometimes I need to tether from my phone. Problem is when I do it uses a random private IP as the network gateway. And Google seems to think they own your phone, not you, so I don't have much control over that behavior. Further I run proxy app on it. What I'd like to do is automate setting it up.

I have the following script:

#!/usr/bin
router=$(route -n | awk '{print $2}' | grep 192.168)
sed "s/\[PROXY-IP\]/$router/g" ~/pac/wpad.template > ~/pac/wpad.dat
export http_proxy="http://$router:8080"
export https_proxy="https://$router:8080"
export ftp_proxy="http://$router:8080"

However when I check env variables, they haven't been set, but the wpad.dat has been updated. So I know the script ran.

I've learned that shell scripts don't access the system env variables. Just local copies. Is there a way to set these variables system wide? The only suggestions I can find would require a reboot every time the network changes. This would be very disruptive. Basically hard coding the script into .bashrc

I've looked into the source command, but that only seems to work for whatever called the script. The changes don't propagate upward to system and user variables. I don't know how they could, since whatever source called the script would be operating on it's own local copy of environment variables.

6
  • You found out that a script can't change the environment of the calling shell, except if you run it with source. Usually, the proxy variables are set globally in /etc/environment, but there is no magic - your shell sources /etc/environment when it starts up. Perhaps there are programs that read from /etc/environment directly, but that would depend on the program. Most programs just inspect the variables, I would guess. May 10 '21 at 2:01
  • I seem to be wrong thinking that the shell uses /etc/environment: superuser.com/questions/664169/…. In any case, which programs do you want to configure with http_proxy? Perhaps there are other ways to configure them. May 10 '21 at 2:07
  • You are successfully changing the WPAD file, so GUI browsers like firefox should automatically use the updated proxy setting. Changing the proxy for command-line programs and tools like lynx, curl, wget, etc is much harder. They can't use a PAC or WPAD file. You can't even change the environment variables in a process's parent process, let alone globally. And there's no way to tell a shell to re-source a file when it changes. The only thing you can do is to update /etc/environment (or some other file) and then remember to manually source that file in every shell that needs it.
    – cas
    May 10 '21 at 7:15
  • Actually, you could probably do some nasty hackery with $PROMPT_COMMAND to source a file if it has changed...but that will slow down every shell prompt while it does that. On every command you run. And it won't effect already-running tools, it can only change the *_proxy variables when the prompt is displayed. And it would only work in bash, not ash/dash/zsh/ksh/etc (you could probable use $PS1 in those, but that's an even uglier hack). NOTE: source aka . does work in PROMPT_COMMAND...I wasn't sure, so I tested it with PROMPT_COMMAND=". /tmp/pc-test.sh". So, ugly but doable.
    – cas
    May 10 '21 at 7:29
  • Just a note: There is no such thing as a "system wide" variable that gets updated with every change. When a process is stared, it receives a copy of it's parent processes environment at the time the process was started. After that, any changes to the environment do not affect any other copy. Similar to making a photocopy of a document and then writing on either does not make the writing appear on the copies or original.
    – C. M.
    May 10 '21 at 21:29
0

You must Source-Call your file (dot befor the call of the file): . ./myfile.sh

Normaly files get only a copy of the parent environment and after closing the session chnces of the child-process in environment is lost

0

Updating the WPAD file should work just fine for GUI browsers like Firefox (assuming they're configured to use it).

Command-line tools like lynx or wget or curl are much harder:

  • They can't use a PAC or WPAD file
  • You can't even change the environment variables in a process's parent process, let alone globally.
  • And there's no way to tell a shell to re-source a file when it changes.

Except that there is a way to do the last item. In bash, at least. You can use the PROMPT_COMMAND variable to tell bash to source a script every time it displays the shell prompt. For example:

Modify your script so that it outputs the *_proxy variable settings to a file, e.g. /var/tmp/proxy-settings.sh. Make sure that file is world-readable, with chmod a+r.

something like:

cat <<__EOF__ > /var/tmp/proxy-settings.sh
export http_proxy="http://$router:8080"
export https_proxy="https://$router:8080"
export ftp_proxy="http://$router:8080"
EOF

Then write a shell script to source that file if it has changed, save it as, e.g., /usr/local/bin/update-proxy-vars.sh. Again, this should be word readable (chmod a+r). It doesn't need to be executable, because it's going to be sourced, not executed:

# each individual shell needs it's own timestamp, because each one will
# read the proxy settings file at different times.
mkdir -p /tmp/.proxy-timestamps

tsfile="/tmp/.proxy-timestamps/time/var/tmp/proxy-settings.sstamp.$$"
if [ -e "$tsfile" ] ; then
  timestamp=$(< "$tsfile")
fi

# get the timestamp of the proxy-settings.sh file
# not all versions of `stat` can do this, and those that do
# have different and incompatible options.  The following works
# for GNU `stat`.
proxy_timestamp=$(stat -c %Y /var/tmp/proxy-settings.sh)

# has the timestamp changed?  if so, source the file.
if [ "$timestamp" != "$proxy_timestamp" ] ; then
  . /var/tmp/proxy-settings.sh
  echo "$proxy_timestamp" > "$tsfile"
fi

Finally, set PROMPT_COMMAND to source this script every time it displays a prompt.

PROMPT_COMMAND='. /usr/local/bin/update-proxy-vars.sh'

You should also run rm -f /tmp/.proxy-timestamps/timestamp.$$ in your ~/.bash_logout script, to tidy up when bash exits.just

This is, IMO, ugly and a nasty hack, and it slows down bash (which is no speed demon to begin with) because it has to run the update-proxy-vars.sh every time it displays a prompt. Every single time you run a command. Or just hit enter with no command. Every prompt, it's going to have to run this script, read in a timestamp file, run stat, compare timestamps, and maybe source another file if the timestamp has changed.

It would probably be faster to just source /var/tmp/proxy-settings.sh every time, if it exists, whether it has changed or not, and not bother with the timestamps.

Just set:

PROMPT_COMMAND='[ -e /var/tmp/proxy-settings ] && . /var/tmp/proxy-settings.sh'

But it works, which is the main thing, right?

Or you could get into the habit of remembering to manually source a file like /var/tmp/proxy-settings.sh in every shell that needs it when it's needed.

You can probably do the same thing using the $PS1 variable in other shells (like ash, dash, zsh, ksh, etc). But this version using PROMPT_COMMAND is ugly and hacky enough. Doing it with PS1 would be even worse.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.