I move between three different network configurations with my powerbook in an average day. Two of these configurations have proxy servers and one does not. Mac OS X has really excellent network location support that lets me configure this stuff once so that switching locations is as simple as invoking QuickSilver, typing the first few letters of the network location and BAM.

Most applications automatically pick up the new proxy configuration but some do not, like Firefox (which is one of three big reasons I still use Safari). I do a lot of work from the command line with network based tools such as curl, wget, port, http_ping, links, svn, etc. None of these use the system proxy settings but most support specifying a proxy server via the http_proxy environment variable.

I've searched high and low for a mechanism that would handle setting the http_proxy variable based on my current network location but have come up with nothing.

First, you need to create a file /etc/http_proxy that specifies the proxy servers for each Network Location you have setup in your Network Preferences (If anyone can figure out how to get the proxy information directly please let me know. I can get the current network location but not information about it). The file might look something like this:

Work = http://proxy.example.com:80
Library = http://proxy.library.com:80

The keys are the names of your network locations and the values are in http://proxy-host:proxy-port form.

Next, you’ll need to put the following script somewhere along your $PATH named proxy-config and give it a chmod +x too.

 #!/bin/bash 

 # source this into your current to have the proxy 
 # environment variables needed by many command line 
 # apps setup correctly.

 # get the current network location name
 netloc=$(/usr/sbin/scselect 2>&1 | egrep '^ \* ' | \
          sed 's:.*(\(.*\)):\1:')

 # find the proxy in /etc/http_proxy based on the 
 # current location
 http_proxy=$(egrep "$netloc[ \t]*=" /etc/http_proxy | \
              sed 's/.*=[ \t]*\(.*\)/\1/')

 if [ -n "$http_proxy" ]; then
   export http_proxy
   export HTTP_PROXY="$http_proxy"
 else
   unset http_proxy
   unset HTTP_PROXY
 fi

 # the rest of this is used for symlink commands
 bn=$(basename $0)
 if [ "$bn" != "proxy-config" ]; then
     dn=$(cd $(dirname $0); pwd)
     for p in $(echo $PATH | sed 's/:/ /g'); do
       [ "$p" != "$dn" ] && [ -x "$p/$bn" ] && exec "$p/$bn" "$@"
     done
 fi

This script has two usage scenarios. You can source this into your current shell to have the http_proxy set correctly based on your current network location:

$ . proxy-config
$ echo $http_proxy
http://proxy.example.com:80

Alternatively, you can create symlinks to the proxy-config script using the names of commands that require http_proxy and the script will automatically set the variable and exec the real command.

Got that? No? Okay, let’s move on.

Pretend you have /usr/bin/curl and you put the script from above at /usr/local/bin/proxy-config. You can get curl to use the approriate proxy settings by doing something like this:

# mkdir /usr/local/proxybin
# cd /usr/local/proxybin
# ln -s ../bin/proxy-config curl
# ls -l
total 4
lrwxr-xr-x  1 root wheel 19 May 11 13:30 curl -> ../bin/proxy-config

As long as /usr/local/proxybin is on your $PATH before /usr/bin, executing curl will actuall call proxy-config. proxy-config will then setup the proxy settings and exec /usr/bin/curl.

Now just create a symlink just like the one made for curl for anything else that requires proxy settings and enjoy network location support from the command line.

More on tools osx bash unix

Discuss

  1. I've found Mark Assad’s identically-named proxy-config program to be exceptionally useful for these situations:

    http://www.cs.usyd.edu.au/~massad/project-proxy-config.html

    It will get the system proxy configuration data from your Network Preferences automatically, and return the appropriate URL for the http, https, and ftp proxies for your current Location.

    To use it, I've put this in my .bashrc:

    function prox() {
      export http_proxy=`proxy-config -h`
      export https_proxy=`proxy-config -s`
      export ftp_proxy=`proxy-config -f`
    }
    
    prox
    

    As a result, the proxy environment variables are set correctly any time I open a terminal window, and I can update it at any time (after changing locations) by typing “prox”.

    Your idea of shell wrappers around the commands that need the proxy is a good enhancement to this… that way “prox” could be automatically invoked right before it’s needed…

    Mike Matthews on Tuesday, May 08, 2007 at 09:07 AM #

  2. Given that I found this post while trying to solve a related problem, no doubt others will too. OS X (since Tiger, I believe) includes a command networksetup that provides access to these settings, among others, e.g.

    sudo networksetup -getwebproxy Ethernet
    

    Hopefully that will be useful to someone.

    Geoff on Monday, April 14, 2008 at 11:52 AM #

  3. I use proxy-config together with vlc (http://www.videolan.org/vlc/) and found that vlc is not happy with a blank value for http_proxy, instead it requires the variable to be undefined if no proxy is to be used. So my shell script for vlc says:

    unset http_proxy http_proxy=proxy-config -h if [ $http_proxy ]; then

    export http_proxy
    

    fi

    Chris on Sunday, April 26, 2009 at 03:53 AM #

  4. Sorry, those lines of code got run together; it was meant to be:

    unset http_proxy
    http_proxy=`proxy-config -h`
    if [ $http_proxy ]; then
        export http_proxy
    fi
    

    Chris on Sunday, April 26, 2009 at 03:56 AM #

  5. After messing around with this problem myself on and off over the last year, I just discovered that you can now get the active proxy information directly from the scutil command line utility (scutil --proxy). Some form of text processing (sed | awk | perl | grep) is still needed to extract the relevant bits, but this at least cuts down the number of steps, and eliminates the need for a user-created config file.

    automandc on Thursday, June 18, 2009 at 07:31 AM #

  6. networksetup command (comment #2) — super-helpful. Thanks.

    Anonymous Coward on Thursday, August 20, 2009 at 02:34 AM #

  7. Sorry, comments are temporarily closed due to a broken spam filter. bbl.