Anthony’s Mac Labs Blog

📦 UNIX Aliases and AutoPkg

Posted 2018 August 03

If you saw my “AutoPkg Level-Up” presentation, either in person at Mac Admins at Penn State or by watching the video of the session posted online, you may have noticed that the slide deck has a few extra slides that I didn’t discuss because I was short on time (or, perhaps, I was lacking brevity in my presentation). This post is about the slides I entitled, “Type It For Me.”

As I mentioned in my presentation, even AutoPkgr users need to use AutoPkg from the command line to implement the Trust Verification features added in version 1.0, and there are great benefits to using the command line to test new recipes. But perhaps, like me, you are not a great typist, or perhaps you tend to always use the same options all the time and would like to save some keystrokes. You could certainly use the text replacement feature in macOS (System Preferences > Keyboard > Text) or you could use a third party tool like TypeIt4Me, TextExpander, or Keyboard Maestro, which would add the ability to limit the scope of your shortcuts to just the Terminal. But UNIX OSes have always had a powerful way to create a command shortcut using the alias command. Here’s a look at how I leverage UNIX aliases to make things easier for me when using AutoPkg at the command line.

Temporary and Every-Session Aliases

The format of the alias command is:

alias name='command string'

Note that I’ve used single quotes here to surround the command string we want to alias (which is the most common method), but you could use double quotes if you prefer. Regardless, if you need to use quotes as part of your command string, use the other type (e.g., use double quotes inside single quotes).

Here’s one alias I used as an undergrad working on UNIX mainframes, since I almost always wanted the long form of ls:

alias ls='ls -la'

In this case, I’ve deliberately mapped the alias to an existing UNIX command (ls); my alias will take priority.[1] Thus, take care when selecting your shortcut text.

You can set up an alias at any time. Once you type it in, it is valid for the rest of your session in that shell (unless you choose to specifically unalias it). A simple example that could save you a lot of keystrokes when using AutoPkg is:

alias ap='autopkg'

You could even choose to use just the letter "a" here instead of "ap", since there is no UNIX a command.

I should also clarify at this point that, unlike the text substitution tools I mentioned earlier that can work system-wide, UNIX aliases only apply to the beginning of a command line command. For example, entering the command ls -ap with the ap alias in place would not expand out to ls -autopkg as it might with one of the tools I mentioned in the introduction.

I could choose to just enter this alias command every time I start a new Terminal window in this user account (perhaps by going back through the recent command history using the Up Arrow key or the history command and then re-running that command), but there is a more permanent way. I can place a list of UNIX commands in a text file named .bash_profile that I place at the root of my home directory.[2] Any commands in that file will load every time I open a new Terminal window when logged in to that account. This is not just limited to alias commands — for example, many users place a command in this file to change the appearance of their shell prompt. But for our purposes, I will only list aliases. A typical ~/.bash_profile file that I use to setup AutoPkg is in this repository: https://github.com/jazzace/autopkg-level-up/blob/master/aliases/.bash_profile — let me go through that file and explain how I use those commands.

Aliases For Recipe Writing and Testing

I believe every AutoPkg(r) user should block recipes that do not pass Trust Verification (i.e. recipes that have been updated since you last verified them). However, when you are creating recipes, there will never be any trust information present, so for that period of time you will need to turn trust verification off.[3] As I mentioned in the presentation, there are two commands that can do this:

defaults write com.github.autopkg FAIL_RECIPES_WITHOUT_TRUST_INFO -bool NO
which turns trust verification off for all AutoPkg recipes I run from that account until I say otherwise, or:
autopkg run -k FAIL_RECIPES_WITHOUT_TRUST_INFO="" recipename.recipetype
which sets the FAIL_RECIPES_WITHOUT_TRUST_INFO flag to empty (false) for just this run of the recipe, which will let the recipe run regardless of the current trust settings.

These are pretty long strings, prone to typing errors; they seem perfect for aliases. My methodology—up until just before my Penn State presentation—was to turn off trust just before testing and turn it back on when I was done. I created two aliases to do this (you’ll need to scroll sideways in the block below to see the whole command):

alias notrust='defaults write com.github.autopkg FAIL_RECIPES_WITHOUT_TRUST_INFO -bool NO ; echo "autopkg recipes without valid trust info are now able to run."'
alias trust="defaults write com.github.autopkg FAIL_RECIPES_WITHOUT_TRUST_INFO -bool YES ; echo 'autopkg recipes without valid trust info will be prevented from running.'"

A couple of points here: the semicolon ends the current command and lets me start a second command; I could string multiple commands together this way if I chose. In this case, I simply provide feedback in the Terminal window that confirms the command’s intent and that it is an AutoPkg-related alias. So when I start testing recipes, I would issue the command notrust and when I was done I would issue the command trust. You could use whatever alias name made sense to you. I’ve also shown you what I meant earlier by using single quotes and double quotes differently in the two commands; they are both syntactically valid, but I would generally recommend using single quotes for the outside pair.

The only problem with that methodology is that sometimes I wouldn’t turn trust back on, whether it was because I was interrupted and didn’t get back to it before my next automated AutoPkg(r) run or I simply forgot. I’d rather not have that potential security hole. Because of the power of aliases, I can easily turn it off just when I run the recipe I am testing, like so:

alias aprnt='autopkg run -vv -k FAIL_RECIPES_WITHOUT_TRUST_INFO=""'

So all I have to do when testing is type aprnt recipename.recipetype and leave trust on all the time. (aprnt stands for “autopkg run, no trust” in my mind — use whatever abbreviation makes sense to you.) I’ve also turned on Verbosity Level 2 (-vv) since I am testing and want that level of detail for debugging. This is going to be my methodology going forward.[4]

Let me briefly go through the rest of the aliases in that file:

apr recipename.recipetype
I used this a lot with my previous recipe testing methodology, as I wanted verbosity on without thinking about it. I will probably change this alias to be non-verbose or have it run what aprnt does now.
Since my recipe list was setup with AutoPkgr, this is an easy way to check my entire list when a trust failure is reported. I still have the option of adding -vv if I want the command to also show the changes (“diff”) since the recipe was last trusted.
updatetrust recipename.recipetype
This is just a typing shortcut that aligns nicely with verifytrust. Remember that an override must be in place for this command to work, since that is where trust information is stored.
You could have a whole series of aliases like this, where you use the alias for AutoPkg and just append one or two letters to signify the verb. Getting information about a processor is something I constantly do when writing a recipe because I want to know what input variables are in play (required and optional) and what output variables (if any) it will produce.

You can confirm at any time what aliases are active in your current shell session by issuing the alias command without any options.[5]

Summing Up

Who knew that abilities I learned when I was an undergrad years ago (OK, decades ago) would make my life easier when using a modern tool like AutoPkg? Take my ideas and experiment with your own variations. I hope that this makes things a little easier for those who don’t spend a lot of time in the Terminal—and for those who do, too.

[1] It is possible to run the original UNIX command by starting with a backslash. In this instance, that would be \ls. [Return to main text]

[2] On macOS, every Terminal window you open is a Login Shell, so placing your configuration commands in ~/.bash_profile will ensure that they are processed. Some general UNIX or Linux references will suggest using ~/.bashrc, as that is the file processed when you run an Interactive Shell (which is different from a Login Shell). That won’t load on macOS without creating a ~/.bash_profile file that has the command source ~/.bashrc in it. So I suggest you skip the middleman. [Return to main text]

[3] The alternative, I suppose, is to make an override for a recipe that is still in development. The problem I find with that approach is that I am usually making more than one recipe in the chain (e.g., a .download and a .pkg recipe). I test each separately, so I would have to make an override for each during testing and remake the override if I added any Input key/value pairs during development. I’d rather just bypass trust verification for my testing period. [Return to main text]

[4] Thanks to Greg Neagle for sleuthing out a workable syntax for this command. I found that using the -k FAIL_RECIPES_WITHOUT_TRUST_INFO=no option would not turn trust off, so Greg suggested an empty string ("") and that worked. This is because the -k or --key option only passes a string value, not the boolean value we need here. In this case, having a null or absent value is treated as False, which is what we want, whereas the presence of any value (even the word “no”) was treated as True. [Return to main text]

[5] If you use or test the ~/.bash_profile file in this repo, take a look at the difference between how the alias command represents my notrust command (where I used single quotes outside and double quotes inside) and my trust command (where I did the reverse). The shell parses both commands correctly, but when it reports the alias, it converts the outside quotes to single quotes. It does not do the same to the inside quotes, however. Instead, any single quotes inside the outer quotes have to be escaped. It does this automatically in my trust example because the two sets of quotes were different, but if you were to try to type it with only single quotes, you would have to put a quoted backslash ('\') in front of each inside single quote. It’s so much simpler to just use single quotes outside and double quotes inside unless there is a technical reason not to do so. [Return to main text]