Tiny Deathstars of Foulness

The colrm command is a simple little command that removes columns from standard input before displaying them on the screen (or piping the text into another file). To use, simply cat a file and then pipe it to colrm followed by the start and then stop in $1 and $2. For example, the following would only list the first column of a text file called testfile:

cat testfile | colrm 2

Not providing a second column in the above command caused only the first column to be displayed to the screen. You could pipe all but the second and third columns of a file to another file called testfile2 using the following:

cat testfile | colrm 2 3 > testfile2

April 9th, 2018

Posted In: bash

Tags: , ,

Leave a Comment

Homebrew is a package manager for macOS. You can use Homebrew to install command line packages on a Mac, provided someone has written a formulae, which is a simple Ruby script that walks through the process for installing all the little bits required for a piece of software.

Installing Homebrew is simple. Run the following command which is listed on the Homebrew homepage (not as root):
/usr/bin/ruby -e "$(curl -fsSL"
This will install the macOS Command Line Tools from Xcode as well as create the following directories (if they’re not already present):
  • /usr/local/Cellar
  • /usr/local/Homebrew
  • /usr/local/Frameworks
  • /usr/local/opt
  • /usr/local/sbin
  • /usr/local/share/zsh
  • /usr/local/share/zsh/site-functions
  • /usr/local/var
Then the script will move all the required bits from to the correct locations. Once done, you can easily install a package if you know the name. For example, I do this on practically every new machine I configure for development:

brew install wget

This one is nice because the dependencies that get installed. And you get the latest versions. Let’s look at the version for wget:

wget -V

Next, let’s use brew to search for something: radius

brew search radius

You’ll see that there’s one item on the local taps: freeradius-server

Let’s install that:

brew install freeradius-server
Now, you’ll find that the bits that make freeradius work are located in /usr/local/Cellar/freeradius-server/3.0.16. If you later need to upgrade that package, use the upgrade verb.

brew upgrade freeradius-server

And finally, to update Homebrew to the latest version, run the update verb:

brew update

March 22nd, 2018

Posted In: bash, Mac OS X

One of the most important skills in any language is to know how a basic if then statement works. You set a variable, you say if that variable matches a given pattern (or doesn’t) then do something or else do something different. If/then/else. Other than that, it’s just syntax, and the annoyance of figuring out the operators and syntax. 

So let’s go through the below script (which checks a Mac to see if grayscale is enabled in Universal Access), line-by-line:
  • Line 1: we’re first going to create a variable called grayscale. We’ll fill it with a 0 or 1, the output of a simple “defaults read grayscale” command
  • If that grayscale variable matches 0 execute whatever is after the then
  • One line just for then followed by the command in the next line (which will optionally allow for an else)
  • Use echo to display the text on the screen that indicates Grayscale is disabled to stdout (which could be redirected if you want to do something after we’re done processing)
  • One line just for the else (optional)
  • The echo to display it’s enabled
  • fi ends the if/then so you can move on to the rest of the script (even if you have nothing after the if/then you’ll need the fi or the script won’t run)
grayscale=`defaults read grayscale`
if [[ $grayscale = 0 ]]
echo "Grayscale is disabled"
echo "User doesn't have a token"

In the above if, we used = as an expression. That’s the most common one you’ll likely use, but there are a lot, including the following:
  • [ -a FILE ] True if FILE exists
  • [ -b FILE ] True if FILE exists and is a block-special file
  • [ -c FILE ] True if FILE exists and is a character-special file
  • [ -d FILE ] True if FILE exists and is a directory
  • [ -e FILE ] True if FILE exists
  • [ -f FILE ] True if FILE exists and is a regular file
  • [ -g FILE ] True if FILE exists and its SGID bit is set
  • [ -h FILE ] True if FILE exists and is a symbolic link
  • [ -k FILE ] True if FILE exists and its sticky bit is set
  • [ -p FILE ] True if FILE exists and is a named pipe
  • [ -r FILE ] True if FILE exists and is readable
  • [ -s FILE ] True if FILE exists and has a size greater than zero
  • [ -t FD ] True if file descriptor FD is open and refers to a terminal
  • [ -u FILE ] True if FILE exists and its SUID (set user ID) bit is set
  • [ -w FILE ] True if FILE exists and is writable
  • [ -x FILE ] True if FILE exists and is executable
  • [ -O FILE ] True if FILE exists and is owned by the effective user ID
  • [ -G FILE ] True if FILE exists and is owned by the effective group ID
  • [ -L FILE ] True if FILE exists and is a symbolic link
  • [ -N FILE ] True if FILE exists and has been modified since it was last read
  • [ -S FILE ] True if FILE exists and is a socket
  • [ FILE1 -nt FILE2 ] True if FILE1 has been changed more recently than FILE2, or if FILE1 exists and FILE2 does not
  • [ FILE1 -ot FILE2 ] True if FILE1 is older than FILE2, or is FILE2 exists and FILE1 does not
  • [ FILE1 -ef FILE2 ] True if FILE1 and FILE2 refer to the same device and inode numbers
  • [ -o OPTIONNAME ] True if shell option “OPTIONNAME” is enabled
  • [ -z STRING ] True of the length if “STRING” is zero
  • [ -n STRING ] or [ STRING ] True if the length of “STRING” is non-zero
  • [ STRING1 == STRING2 ] True if the strings are equal. “=” may be used instead of “==” for strict POSIX compliance
  • [ STRING1 != STRING2 ] True if the strings are not equal
  • [ STRING1 < STRING2 ] True if “STRING1” sorts before “STRING2”
  • [ STRING1 > STRING2 ] True if “STRING1” sorts after “STRING2” 
  • [ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers
Attribution: The above list of expressions was originally borrowed from

March 4th, 2018

Posted In: bash, Mac OS X

Tags: , ,

This New Years Day, Learn The Jot Command The jot command is one I haven’t used in awhile. But it’s still useful. Let’s take a look at a few of the things you can do with it. First, let’s just print lines into a new file called “century.txt” which we can do by running with the number of increments followed by the starting number, and then redirecting the output into the file name:

jot 100 1 > ~/Desktop/century.txt

Or to do integers instead, simply put the decimals:

jot 100 1.00 > ~/Desktop/century.txt

Or in descending order,

jot – 100 1 > ~/Desktop/century.txt

Now we could change the output to be just 50 to 100, by incrementing 50 (the first position) and starting at 50 (the second):

jot 50 50

The jot command is able to print sequential data, as we’ve seen. But we can also print random data, using the -r option. Following that option we have three important positions, the first is the number of iterations, but the next two are the lower and upper boundaries for the numbers, respectively. So in the below command we’ll grab 10 iterations (or ten random numbers) that are between 1 and 1000:

jot -r 10 1 1000

Now if we were to add a -c in there and use a and z as the upper and lower bounds, we’d get… letters (this time we’re just gonna’ ask for one letter)!

jot -r -c 1 a z

Something I find useful is just to shove random data into a file infinitely. And by useful I mean hopefully not left running overnight on my own computer (been there, done that). To do this, just use a 0 for the number of iterations:

jot -r -c 0

Something that is actually useful is the basic ASCII set:

jot -c 128 0

We can also append data to a word using -w. So let’s say we want to print the characters aa followed by a through z. In the below we’ll define that with -w and then we’ll list those two characters followed by %c which is where the character substitution goes and then the number of iterations followed by the lower bound:

jot -w aa%c 26 a

You can also do stuttering sequences, useful for the occasional tango dancer, so here we’ll do a 5/3 countdown:

jot – 100 0 -.5

Or we could create a one meg file by creating 1,024 bytes:

jot -b 0 1024 > onemegfile.txt

Oh wait, that file’s two megs. Get it? 😉

And running strings teaches you that you can’t bound random (a good lesson for the New Year). Anything you use jot for?

Happy New Years!

January 1st, 2018

Posted In: bash, Mac OS X, Mac OS X Server

Tags: , , , , ,

In the following example script, I’m going to pull a list of just the usernames from fdesetup. sudo fdesetup list The output would be as follows:
charlesedge,F4D8B61D-1234-1234-98F4-103470EE1234 emerald,2E1203EA-1234-4E0D-1234-717D27221234 admin,50058FCF-88DF-1234-1234-91FCF28C0488
I’ll then pipe them into sed and use the , as a delimiter, pulling * or everything before it: sudo fdesetup list | sed 's;,.*;;' As follows:
charlesedge emerald admin

August 29th, 2017

Posted In: bash, Mac OS X, Mac OS X Server

Tags: , , ,

Builtin commands are always kinda’ interesting. At first glance, it’s hard to know which commands are builtins. Luckily, there’s a command that I rarely use, called… command. If you run command with the -V flag it will tell you if the command is a builtin: command -V cd
cd is a shell builtin
If you run a command that isn’t a builtin command -V ls
ls is /bin/ls
Some builtins are in /bin (like echo). But not all builtins are in /bin. Some are in /usr/bin (like cd). Information about how to use builtins is built into the help command rather than standalone man pages. So, if you do help followed by the name of a command, you’ll get information about the command, and sometimes how to use the command: help cd
cd: cd [-L|-P] [dir] Change the current directory to DIR. The variable $HOME is the default DIR. The variable CDPATH defines the search path for the directory containing DIR. Alternative directory names in CDPATH are separated by a colon (:). A null directory name is the same as the current directory, i.e. `.’. If DIR begins with a slash (/), then CDPATH is not used. If the directory is not found, and the shell option `cdable_vars’ is set, then try the word as a variable name. If that variable has a value, then cd to the value of that variable. The -P option says to use the physical directory structure instead of following symbolic links; the -L option forces symbolic links to be followed.
There are also commands not in a path, which can be found using the which command: which dsconfigad

May 6th, 2017

Posted In: bash, Mac OS X

Tags: , , , ,

One of my favorite things about grabbing things with scripts is just how many ways (and sometimes how needfully or needlessly convoluted you can make them) to grab the same pieces of information. For example, something as simple as what hosts you use to resolve names on a Mac. There are a number of ways to grab what DNS server a device is using in macOS. So when you’re running a script you might choose to grab DNS information one way or another, according to what you’re after. Some of this might seem more complicated than it should be. And that’s correct…


The /etc/resolv.conf file is updated automatically to look at what servers are used to resolve names used for DNS. The easiest way to see theses to simply cat it and grep for nameserver: cat /etc/resolv.conf | grep nameserver


The next way we’ll grab DNS information is using scutil. Here, we use the –dns option, which outputs a lot of DNS stuffs, including all the built-in resolvers: scutil --dns To just grab the name servers: scutil --dns | grep nameserver We can also simplify the output to just the servers with awk: scutil --dns | grep nameserver | awk '{print$3}'


The second way is using networksetup. This command has an option to get a DNS server in (shocker) -getdnsservers. However, you have to list the interface for each. So below we’ll dump all interfaces into an array using -listallhardwareports and then read them in using a for loop and querying the name servers. interfaces=( "$(networksetup -listallhardwareports | grep Hardware | cut -c 16-900)" ) for i in "${interfaces[@]}" do networksetup -getdnsservers $i done The one tricky thing in this one is I initially forgot to quote the interfaces as they went into the array, which meant each word of the interface was an item in the array and therefore the -getdnsservers option failed. Once I quoted, it was all happy. The other thing I can point out is I used cut instead of sed because it was easier to quote; however, it seems unlikely the name can be more than 890 characters, so I think it’s fine…


You can also use dig. Here, you’ll query for a name without using an @ option, but omit everything but the line with the server that responded: dig | grep SERVER: The output is kinda’ fug:
For simpler output, we’ll use sed to constrain the output to just what’s between the parenthesis: dig | grep SERVER: | sed 's/^.*(//;s/)$//'


nslookup is a tool similar to dig, used for querying names. We’ll basically do the same thing as above, just using awk as it’s just a standard position in a line: nslookup | grep Server: | awk '{print$2}'


Then there’s system_profiler, the command line interface for System Profiler. Here, we can query the SPNetworkDataType. This is going to produce a lot of output, so we can limit it to just the DNS servers using grep to constrain to just the lines we want and awk for just the columns in those lines, as follows: system_profiler SPNetworkDataType | grep "Domain Name Servers:" | awk '{print$4}'


@knapjack added to use hosts. I had to use verbose mode to pull the local name server as follows: host -v -t ns | grep Received | awk '{print $5}'


Thanks to the lovely Allister (@sacrilicious), we also have ipconfig to add to the list: /usr/sbin/ipconfig getpacket en0 2> /dev/null | grep name_ | cut -d' ' -f3- There are tons of ways to find things in macOS. Do you have a way to find a DNS server that I didn’t think of here?

March 6th, 2017

Posted In: bash, Mac OS X, Mac OS X Server, Mac Security, Ubuntu

Tags: , , , , , , ,

Recently someone asked me about accepting bash inputs. So I decided to take a stab at writing a little about it up. For the initial one we’ll look at accepting text input. Here, we’ll just sandwich a read statement between two echo commands. In the first echo we’ll ask for a name of a variable. Then we’ll read it in with the read command. And in the second echo we’ll write it out. Using the variable involves using the string of the variable (myvariable in this case) with a dollar sign in front of it, as in $myvariable below: echo "Please choose a number: " read myvariable echo "You picked $myvariable" Read also has a number of flags available to it:
  • -a assigns sequential indexes of the array variable
  • -d sets a delimiter to terminate the input
  • -e accepts the line.
  • -n returns after reading a specified number of characters
  • -p prompts without a trailing newline, before attempting to read any input
  • -r doesn’t use a backslash as an escape character
  • -s runs silent, which doesn’t echo text
  • -t: causes read to time out (number of seconds is right after the -t)
  • -u reads input from a file descriptor
Next, we’ll build on that read statement (note the addition of -p) and use a while to force a user to input a y or n and then parse their selection with a basic case statement: while true; do read -p "Do you wish to continue?" yn case $yn in [Yy]* ) echo "Add your action here"; break;; [Nn]* ) exit;; * ) echo "Please answer yes or no.";; esac done Finally, let’s look at positional parameters. Here, you can feed them at the tail end of the script, as words that are separated by spaces after the name of the script. Here, we simply just echo $0, which is the first position (aka – the name of the script you just ran) and $1 and $2 as the next two. #!/bin/bash echo "You Used These" echo '$0 = ' $0 echo '$1 = ' $1 echo '$2 = ' $2 You could also take $3, $4, etc. This is different than writing flags, which requires a bit more scripting. So if you called the script with: /path/to/script/ test1 You would see: You Used These $0 = ./ $1 = test1 What tips/additions do you have?

February 14th, 2017

Posted In: bash, Unix

Tags: , , , , , ,