networksetup – Change Network Settings from the Command Line

UPDATE (8/12/08): I simplified the awk portion of the command.

Mac OS X comes with a very convenient tool called networksetup that makes it relatively easy to view or change network settings from the command line. In Leopard, the command is readily available at /usr/sbin/networksetup. Since /usr/sbin exists in the default path, you can access the command directly. In Tiger, Panther, and Jaguar, the command is not anywhere in the default path, but lives buried within the bundled ARD Agent at /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support/networksetup. (If you’re not using Leopard, be sure to include the full path to the executable in all of your commands.) Apple’s man page for networksetup covers all the available options but it’s short on real examples of its use.

Let’s say you manage a menagerie of mottled (i.e. striped or spotted) Macs on a non-dhcp, statically-addressed network. Let’s also say that your network’s DNS servers are about to change addresses to 10.0.0.11 and 10.0.0.12. Without the convenience of dhcp, you’ll have to modify the network configurations of each Mac. Fortunately, networksetup makes it easy. The command you’ll need to use — which must be run as root — takes the following format:

networksetup -setdnsservers networkservice dns1 [dns2] [...]

where networkservice is the display name of the interface (e.g. Built-in Ethernet, Airport) that you want to modify, and dns1, dns2, etc. are the ip addresses of the new dns servers. Depending on the kinds of Macs you manage, you’ll likely have to use two or more versions of this command to update all Macs with your new network settings. Mac Pros have up to three network interfaces (Built-in Ethernet 1, Built-in Ethernet 2, AirPort), iMacs, MacBooks, and MacBook Pros have two (Built-in Ethernet, AirPort), and MacBook Airs have up to two (AirPort, USB Ethernet).

So, for example, an iMac that uses its ethernet interface to access your network needs to be sent

sudo networksetup -setdnsservers "Built-in Ethernet" 10.0.0.11 10.0.0.12

while a MacBook that uses its wireless interface needs

sudo networksetup -setdnsservers "AirPort" 10.0.0.11 10.0.0.12

to update its dns settings.

What if you want a one-size-fits-all command?

I’m glad you asked. Since you can safely assume, in most cases, that the default network interface is the one you want to update, this task begs for a scripty solution. We can use another feature of the networksetup command to determine the default network interface.

networksetup -listnetworkserviceorder

This lists the computer’s network interfaces in their priority order. On my MacBook Pro, I get

    (1) Built-in Ethernet
    (Hardware Port: Ethernet, Device: en0)

    (2) AirPort
    (Hardware Port: AirPort, Device: en1)

    (3) Built-in FireWire
    (Hardware Port: FireWire, Device: fw0)

    (4) Bluetooth
    (Hardware Port: Bluetooth, Device: Bluetooth-Modem)

The only part of this result we care about is the text that comes after the “(1)” on the first line. awk can extract that for us.

networksetup -listnetworkserviceorder | awk -F'\\) ' '/\(1\)/ {print $2}'

Crash course in awk

If you’re not an awk-lover, then this command may need some explanation. Before I dive in, I’ll just tell you that awk is a powerful text search and text-processing language. By default, it breaks down search results by whitespace and assigns resulting “words” into numbered variables. $0 is the entire result, $1 is the first word, $2 is the second word, etc. Any manipulation you want to do with the awk command is put into curly brackets and separated by semicolons.

There are many great resources online to help you learn awk, so I won’t go into too much detail here.

Now let’s break down the command.

awk -F'\\) ' '/\(1\)/ {print $2}'

-F'\\) '
The -F switch tells awk that the character or characters immediately following it should be used as word delimiters. In this case, I want awk to use a closing parenthesis followed by a space to delimit words — “) “. (Note that the closing parenthesis needs to be double-escaped.) If you’re using more than one consecutive character as a delimiter, the characters must be enclosed in single quotes. Including a space in your delimiter is a handy way of excluding leading spaces from your results.

/\(1\)/
This section tells awk that you want it to operate only on lines containing “(1)”. (You need to escape the parentheses.) In this example, we’re looking at the first line only: “(1) Built-in Ethernet“. Now, moving within the curly brackets, we have…

print $2
This tells awk to spit out the second word of the line. Since we used “) ” as our delimiter, the second word will be everything after the “) ” on the line that contains “(1)”.

Also, note that the search portion and the command portion are enclosed in single quotes. The entire awk command turns this

    (1) Built-in Ethernet
    (Hardware Port: Ethernet, Device: en0)

    (2) AirPort
    (Hardware Port: AirPort, Device: en1)

    (3) Built-in FireWire
    (Hardware Port: FireWire, Device: fw0)

    (4) Bluetooth
    (Hardware Port: Bluetooth, Device: Bluetooth-Modem)

into this

Built-in Ethernet

The payoff — a universal DNS changing command

Now, attaining our universal command is simply a matter of assigning the output of our piped-to-awk command to a variable and then using that variable in the setdnsservers command. Since you’ll likely want to use ARD to send this command out, leave out the sudo portion as you can specify this to be run as root from ARD.

    mainInt=$(networksetup -listnetworkserviceorder | \
    awk -F'\\) ' '/\(1\)/ {print $2}')
    networksetup -setdnsservers "$mainInt" 10.0.0.11 10.0.0.12

The quotes around $mainInt in the last line are important because the interface name may contain spaces.

But wait, there’s more

Now that you can get the default network interface name, you can easily change other network settings — e.g. proxies, search domains, dhcp — on all your Macs with the same basic command format.

Want to change your search domains?

    mainInt=$(networksetup -listnetworkserviceorder | \
    awk -F'\\) ' '/\(1\)/ {print $2}')
    networksetup -setsearchdomains "$mainInt" sub.domain.com domain.com

Want to convert from static addressing to dhcp?

    mainInt=$(networksetup -listnetworkserviceorder | \
    awk -F'\\) ' '/\(1\)/ {print $2}')
    networksetup -setdhcp "$mainInt"

The possibilities may not be endless, but they’re definitely plentiful.

Advertisements

28 thoughts on “networksetup – Change Network Settings from the Command Line

  1. Hey buddy… So I have a similar setup process I use to configure my network settings when doing deployment. Do you have any tricks for configuring wep and or wpa settings, and ensuring that the key is added to the keychain?

  2. I’ve never tried to do that. The wireless network in the building where I work has no access to internal resources — just the internet. It’s a “guest” network, so we don’t use keys.

  3. Just a follow-up…. I tried a number of different methods to add a keychain for my wireless interface… The best results came when I used the latest version of Package Maker to install the key though a snapshot. Typically I do not like to use snapshot, but in this case it worked pretty well. Figured I would post this if anyone is wanting to work around WEP and WPA keys :-)

  4. Thanks for letting me know your findings. I know Apple worked on Package Maker a lot in Leopard. Perhaps it’s time to reevaluate my distaste for the snapshot method.

  5. Great tips on awk. One question — how come a dollar sign is needed when defining the variable on the right side of the equal sign?

    > mainInt=$(networksetup…….

    Thanks a lot!
    David

    • The ‘variable=$(blah)’ construct is a way of assigning the result of a shell command to a bash variable. You can alternatively use backtics, e.g. mainInt=`networksetup…` — but I prefer the $() method. Everything inside the parentheses is a shell command you can run in the terminal.

  6. Hi Pmbuko,

    A very informative blog related to the nix / osx world. I am very new to OSX and scripting, is there a way we can script a VPN (PPTP) setup on mac clients (Leopard / SL). So basically when we email / transfer this applescript to our end user they would be able to run it and setup a vpn connection so that they can connect to our work (windows server PPTP VPN Server).

    I have a question on stackoverflow for this : http://stackoverflow.com/questions/4265354/applescript-deploy-pptp-vpn-settings-to-mac-clients

    Thanks again for the informative post / blog
    Kind Regards

    • I’m not aware of any way to do it using applescript or shell scripting, but there’s a relatively new GUI scripting language called Sikuli that would be able to do it. Basically, you take screenshots of all the steps required, and then tell Sikuli where to click and what to type. Pretty powerful stuff when other methods won’t work. http://sikuli.org/

  7. Hi Pmbuko,

    Thanks for your reply, sikuli looks good, but if you follow the stackoverflow link you would see a applescript there which does what it says in the script, I thought you may be aware of applescript and might be able to guide me on what commands to use to insert service name, dns address, routes into that vpn script.

    Still, good point with sikuli – thanks !

  8. Hi Peter

    mainInt=$(networksetup -listnetworkserviceorder | awk -F’\\) ‘ ‘/\(1\)/ {print $2}’)

    is pointing to the bluetooth network for both Mac Pro and iMac ,

    i am not sure why the mac are defaulting as bluetooth as priority

  9. What if we wanted to grab multiple values from this example? Say we continue parsing the output of ‘networksetup -listnetworkserviceorder’ .. what If I wanted to glean three variable from each multi-line-record so I ended up with
    $1servicename = “Built-in Ethernet”
    $1hwport = “Ethernet”
    $1devid = “en0
    $2servicename = “AirPort”
    $2hwport = “AirPort”
    $2devid = “en1”

    How would I accomplish this using awk?

    • I wouldn’t use awk for something like that, even though it’s possible. This would be a great job for perl, which could do it far more elegantly.

  10. Is it somehow possible to change/set the “Service Order” of the Mac OS X (10.6, soon 10.7 in my case)?

    I have a Mac Pro with 2 ethernet connections, both active and used for different things, I usually have to go into System Prefs > Network > Set Service Order at least 3-4 times a day depending on what I do and what network needs to be my primary, it would be awesome if there was a way to simply run a terminal command / script that I could run to not always have to do all those steps.

    Anyway, would love to know if that’s even possible via the CLI.

    Great post by the way, thanks.

    • Indeed it is possible. First run ‘networksetup -listnetworkserviceorder’, then run ‘networksetup -ordernetworkservices “a” “b” “c” …’, replacing the letters with the actual name of the interface as reported by the first command. Leave the quotation marks around any interface names that have a space in them. If you constantly toggle between a couple different configurations, you can save the specific commands as aliases in your .bashrc file. To do this, open the terminal and type ‘nano .bashrc’, and then add lines like this to the end of the file:
      alias netorder1='networksetup -ordernetworkservices "a" "b" "c"'
      alias netorder2='networksetup -ordernetworkservices "b" "a" "c"'

      Save by typing ^O and Enter, then ^X to exit.
      Now type ‘source .bashrc’ and then test your commands: ‘netorder1’ and ‘netorder2’

  11. Thank you SO MUCH. I find the GUI network set-up utility on Snow Leopard as flaky as all-get-out – forgets passwords, even.

  12. I was wondering if you knew how to add a second network location via a script? Using Mac OS X MLion. I want to keep the Automatic loc and add one called “Office” with the wireless service removed from this location.

  13. I executed
    networksetup -setsearchdomains “Ethernet” office.intranet

    but when I perform
    nslookup build.office.intranet

    it does not resolve the IP. What I am doing wrong?

Comments are closed.