Superb.
Superb.
An amazing run of the snooker table.
July 23, 2014 | posted in: nerdliness
Today I had need to rename several roles used in our Chef configuration. They had been created with dashes rather than underscores in their names and that prevented me from use the role name as a Ruby symbol. For example, while my-role might be a perfectly good name, :my-role as a Ruby symbol doesn't work. Renaming the roles is only part of the problem, finding all occurrences of the role in all the run-lists and updating those occurrences is the real trick.
A word of caution: As with any code you find on the Internet, you should review the script and commands given below to assure yourself you know their impact. Mass changes can have far reaching consequences.
First off you need to download the role from the Chef Server to your workstation.
$ knife download roles
(This command actually gets all your roles.)
Next, rename the file.
$ mv my-role.json my_role.json
Now edit the file and correct the JSON "name": to match the new file name.
$ vim my_role.json
Upload the new role to your Chef Server
$ knife role from file my_role.json
On your Chef server now you should have two roles, one with a dash and one with an underscore that have identical contents.
To update all run-lists I used this script, which I found here: renaming a role
role_from = ARGV[2] # format role[foo]'
role_to = ARGV[3]
if ARGV.length > 3 and ARGV[4] == 'dry-run'
dry_run = true
else
dry_run = false
end
puts role_from
nodes.all do |node|
if node.run_list.include?(role_from)
puts "match #{node}, current run_list #{node.run_list}"
if node.run_list.include?(role_to)
puts "ERROR #{node} has #{role_from} and #{role_to} skipping"
next
end
pos = -1
node.run_list.each_with_index do |item, index|
if item == role_from
pos = index
break
end
end
node.run_list.run_list_items[pos] = node.run_list.coerce_to_run_list_item(role_to)
puts "\tchange <at> pos=#{pos} new run list #{node.run_list}"
if dry_run == false
node.save()
puts "\tsaving node #{node}"
end
end
end
exit 0To run this, save the script somewhere on your workstation. I put mine in my ~/.chef directory in a new sub-directory called scripts. Once the script is saved run this knife exec command.
$ knife exec ~/.chef/scripts/rename_nodes.rb "role[my-role]" "role[my_role]"
Optionally you can do a dry-run of the script to see its impact before making any changes.
$ knife exec ~/.chef/scripts/rename_nodes.rb "role[my-role]" "role[my_role]" dry-run
You must specify the enclosing role[ ... ] otherwise the matching performed by the rename_nodes script won't work.
All your nodes should now be using the new role name. As a final step you can restart the Chef Client on all your nodes.
$ knife ssh 'name:*' 'sudo /etc/init.d/chef-client restart'
Once everything checks out you can remove the old role.
July 02, 2014 | posted in: nerdliness
When I am wearing my operations hat at work I need ready access to a number of servers, 15 or so. I use tmux to create a “console” session that is broken into 5 separate windows, each further divided into panes (one per server). The windows are rough categories: production, alpha, web, ESB, etc. I also normally have a “tools” session in a separate Terminal instance that contains 4 more windows, each to utility servers that I use periodically throughout the day.
Rather than try to create these tmux sessions by hand I’ve been using a tool called teamocil to capture the session::window::pane configuration in YAML files. With a console.yml file I can setup the entire console session with a single command.
Here’s how I set things up.
First you need to install the teamocil Gem.
$ gem install teamocil
Next you’ll need a space to keep the YAML files that describe your tmux sessions. teamocil expects this to be called ~/.teamocil
$ mkdir ~/.teamocil
teamocil comes with a command that will use your $EDITOR to create new session configuration files.
$ teamocil —edit console
The teamocil web site has good documentation on the options and attributes required to setup a configuration. Here is a sanitized version of my console.yml file.
session:
name: "console"
windows:
- name: "prod"
root: "~"
options:
synchronize-panes: true
layout: even-vertical
panes:
- cmd: "ssh prod1"
- cmd: "ssh prod2"
- cmd: "ssh prod3"
- cmd: "ssh prod4"
- name: "web"
root: "~"
options:
synchronize-panes: true
layout: even-vertical
panes:
- cmd: "ssh web1"
- cmd: "ssh web2"
- cmd: "ssh web3"
- cmd: "ssh web4"
- cmd: "ssh web5"
- name: "esb"
root: "~"
options:
synchronize-panes: true
layout: even-vertical
panes:
- cmd: "ssh hub1"
- cmd: "ssh hub2"
- name: alpha
root: "~"
options:
synchronize-panes: true
layout: even-vertical
panes:
- cmd: "ssh alpha1"
- cmd: "ssh alpha2"
- cmd: "ssh alpha3"
- cmd: "ssh alpha4"The name attribute is the name that will appear in my tmux status bar. root sets the directory in which each pane will be created. The synchronize-panes option is particularly nice as it allows me to type commands in one pane and have them run in all panes. The layout attribute determines whether the panes are vertically stacked, horizontally arranges or tiled.
Since I have my terminal set to create or reattach to my base tmux session creating my console session is one command away.
$ teamocil console
In seconds I have 5 windows (the original, prod, alpha, web, and ESB), each subdivided in to as many panes as there are servers. Quick, simple, repeatable.
July 01, 2014 | posted in: nerdliness
Recently I purchased a new MacBook Pro laptop. Here’s how I synchronized my iPhone 5 and my iPad Mini to the new computer. Both were mated to my previous MacBook Pro.
By design your iDevice can only be synced with one computer at a time. Also by design the synchronization process is one way: from computer to iDevice. This means that photos or music on your iDevice that aren’t backed up will be lost if you just sync with the new computer.
Make a back up to the old computer. Better safe than sorry.
Authorize iTunes on the new computer. With iTunes running select “Authorize This Computer…” from the “Store” menu. This allows your new computer to access any purchased music, movies, books, or apps.
Turn automatic synchronization off. Open up “Preferences” in iTunes and select the “Devices” tab. Once there check the “Prevent iPods, iPhones, and iPads from syncing automatically” option.
Download all purchased content. Visit the iTunes Store (sign in with your account if necessary) and select the “Purchases” option from the Home screen. For each category (Music, Movies, TV Shows, Apps, and Books) click the “Download All” button. Depending on your past purchases this may take a while. The idea here is to have any and all purchased content that might be on your iDevice on the new computer before syncing it the first time.
With iTunes running connect your iDevice. Do not sync at this point.
Right-click on your iDevice in the in the sidebar and select “Reset warnings”. You may need to click on the ‘View/Show Sidebar’ menu option to see your device,
Right-click on your iDevice again and select “Backup”. This will create a new back up of your device on your new computer.
Right-click one more time and select “Restore from Backup”, select the backup you just made. When prompted to create another backup, decline. This will restore your iDevice using the newly created backup.
You MUST now sync your iDevice to restore your iTunes content, which you will select from various tabs in iTunes. You’ll get a popup regarding your contacts and calendars asking to merge or replace. Select “merge”.
There is no step 10. You are done. You iDevice should look just like it did when you started, with no data loss.
April 20, 2014 | posted in: life
Dear American Airlines,
On Friday, April 18, 2014, I was returning from a conference in San Francisco California. My flights that day were from SFO to Chicao's O'Hare airport, and then from ORD to Manhattan Kansas. My flight number was 1585, leaving SFO at 11 am for ORD. I arrived at the airport very early and was at my departure gate two-and-a-half hours before the scheduled 11 am flight.
At approximately 10:30 am the boarding process began. When group 2, my assigned group, was called I entered the line and presented my boarding pass. The gate agent scanned it and said, "That's not the right name." He scanned it a second time and more forcefully said to me, "That's not the correct name." I pulled up the electronic boarding pass on my phone and showed that to him and he for the third time said, "That's not the right name!" Visions of large, unsmiling men escorting me away from the gate appeared in my head.
A woman at the counter, who I later learned was the supervisor, came and took me aside and handed me a new boarding pass. My seat assignment had been changed from 12F to 8B. I demanded to know why I was being moved to a middle seat when I had purchased a window seat months earlier. Supervisor Mcosey (phonetic spelling) said something about another passenger who didn't speak English. I asked why that meant I had to lose my seat. I was bitterly upset about being forced to sit bewteen two other people for a 4 hour flight. She said "I put you at the bulkhead where you'd have more room." I said that the bulkhead meant my backpack, containing several thousand dollars worth of computers would have to go in the overhead and risk being crushed by other bags.
Since all ariports are now places of security theater I was acutely aware of making a scene. I looked at Supervisor Mcosey and said, "You have me over a barrel here, I don't have a choice, do I?" and took the boarding card and stormed down the jetway.
During the boarding process the gate agent who had been confused by my boarding pass appeared on the plane. I asked him for an explanation and he was unable to provide one. He didn't know why I had been moved and said it has been done by Supervisor Mcosey. He did volunteer to try and get me on another flight to Chicago, but with only one remaining connecting flight that day to my final destination I didn't feel like that was a viable option.
After the plane was airborne one of the flight attendants helped a barely able to walk passenger to the forward lavatory and then came to talk to me. She explained that the passenger she had helped had been moved from 12E to 12F. She was willing to put the passenger back in to 12E and move me to 12F. When I asked how she would explain this to the other passenger who apparently had no English she couldn't answer. I stayed in 8B. I believe that the passenger who had been moved ended up with two seats, 12E and 12F all to herself as a result of this fiasco.
I have filled out your online complaint form and submitted it. My reference number is 1-1383184011. Here is the text I submitted with my complaint:
I demand an explanation as to why Supervisor Mcosey (phonetic spelling) changed my seat assignment from 12F to 8B at the last minute without telling me, or involving me in that process. I wasn't aware of the change until my name on the boarding pass didn't match the name on the display when the gate agent scanned it as I was boarding. I do not understand why I was moved from the window seat I had paid for for a middle seat at the bulkhead.
Not only was I not aware of the seat change, the gate agent wasn't aware of it either. He was understandably confused by the wrong name appearing when my boarding card was scanned. I felt like I was being accused when my boarding card didn't work. I found the accusation stressful and upsetting, particularly since I had no idea what was happening. The accusation left me frightened and upset.
- Why was I moved?
- Why wasn't I, or anyone else, informed of the move or involved in that process?
- What will be done to ensure this kind of unilateral change won't happen again?
The entire experience was extremely upsetting and disturbing, and unnecessarily so.
Consider me an extremely disastisfied customer. Unilateral changes made without the participation of or knowledge of the passenger are terrible customer service.
April 10, 2014 | posted in: nerdliness
I recently discovered feedshare.net which allows you to share your RSS OPML file with the world. So without further ado, here's my RSS feed list. All 328 of them.
March 04, 2014 | posted in: nerdliness
Here's how I have setup my laptop running OS X Mavericks (10.9.1) for Chef.
Install VirtualBox 4.x..
Install Vagrant 1.4.1 (or higher).
Set up a sane Ruby 1.9.x environment for Chef cookbook authoring Note: On OS X Mavericks (10.9.x) the system (default) Ruby is 2.x and therefore you may not need to install a Ruby version manager (RVM, rbenv, or chruby).
Install Berkshelf
$ gem install berkshelf --no-ri --no-rdoc
Fetching: berkshelf-2.0.10.gem (100%)
Successfully installed berkshelf-2.0.10
1 gem installed
$ berks -v
Berkshelf (2.0.10)
Copyright 2012-2013 Riot Games
Jamie Winsor (<jamie@vialstudios.com>)
Josiah Kiehl (<jkiehl@riotgames.com>)
Michael Ivey (<michael.ivey@riotgames.com>)
Justin Campbell (<justin.campbell@riotgames.com>)
Seth Vargo (<sethvargo@gmail.com>)$ vagrant plugin install vagrant-berkshelf
Installing the 'vagrant-berkshelf' plugin. This can take a few minutes...
Installed the plugin 'vagrant-berkshelf (1.3.7)'!$ vagrant plugin install vagrant-omnibus
Installing the 'vagrant-omnibus' plugin. This can take a few minutes...
Installed the plugin 'vagrant-omnibus (1.2.1)'!Open a browser and navigate to http://www.getchef.com/chef/install. Select OS X in the Operating System drop down. Choose the version number closest to your current OS X version, likely 10.7. Select x86_64 for the architecture. Copy the curl command from the Quick Install Instructions section and run it.
Once you've completed the setup process for your workstation open a command prompt and verify your installation is working.
$ chef-client --version
Chef: 11.10.0Create a directory to hold your Chef authentication keys. For example:
$ mkdir ~/.chefIf you are using a hosted Chef server the Chef Starter Kit will include your account authentication key, the Chef Server authentication key, and a knife.rb configuration file for that server. While you can leave your authentication keys in the chef-repo the starter kit provides, I choose to copy them to my ~/.chef directory as I access multiple chef servers and centralizing the authentiation keys simplifies things.
$ cp ~/Downloads/chef-repo/.chef/*.pem ~/.chefIf you are using a locally hosted open soure Chef Server, contact the administrator for that server to have an account created. Once your account has been created you can generate a new authentication key by following these steps.
Sign into your account on the Chef Server and then
Click on the edit account link in the upper-right corner of the page
Check the box under Regenerate Private Key and click the Save User button. Note: Regenerating your private key means any previous key will no longer work.
Copy your entire private key to your workstation naming it your-id.pem and saving it in the ~/.chef directory you created above. If you are setting up more than one workstation, copy the key to those workstations as well.
The administrator for the Chef Server can also proide you with the server's validator.pem. Once you have received that file, copy it to your Chef keys directory as well, calling it chef-validator.pem.
Your Chef authentication keys directory should now look similar to this:
drwxr-xr-x 10 mhn staff 340B Jan 7 14:11 ./
drwxr-xr-x+ 77 mhn staff 2.6K Mar 2 10:37 ../
-rw-r--r-- 1 mhn staff 1.6K Jan 7 14:08 chef-validator.pem
-rw-r--r-- 1 mhn staff 1.6K Jan 7 14:06 you.pemCreate a directory on your workstation to be the root of all your Chef activities. For example:
$ mkdir -p ~/Projects/chefThe Chef Repository, or chef-repo, provides a structure for all the components of Chef: cookbooks, recipes, templates, attributes, roles, et cetera.
If you are using a hosted Chef Server, the same starter kit mentioned above will include a chef-repo for your use. Copy it to your newly created project directory.
To create a chef-repo yourself follow these steps:
$ cd ~/Projects/chef
$ wget http://github.com/opscode/chef-repo/tarball/master
$ tar -zxf master
$ mv opscode-chef-repo* chef-repo
$ rm masterNote: On OS X you may need to run brew install wget to add that utility to your system.
knife is the Chef command line tool. It is an API-client that is used to communicate with the Chef Server, and also to perform some activities on your workstation. knife is included with Chef and was installed when you added Chef to your workstation.
If you are working from a stater kit you already have a completed knife.rb file and can skip ahead to "Testing your knife.rb configuration".
Create a .chef directory in your chef-repo.
$ cd ~/Projects/chef/chef-repo
$ mkdir .chefUsing your favorite editor create a new file, knife.rb in the .chef directory. The file contents should look like this:
current_dir = File.dirname(__FILE__)
node_name 'your-id'
client_key '/Users/you/.chef/your-id.pem'
validation_client_name 'chef-validator'
validation_key '/Users/you/.chef/chef-validator.pem'
chef_server_url 'https://path.to.your/chef-server'
cache_type 'BasicFile'
cache_options( :path => '/Users/you/.chef/checksums' )
cookbook_path ["#{current_dir}/../cookbooks"]
cookbook_copyright 'Your Name'
cookbook_license 'reserved'
cookbook_email 'you@example.com'
log_level :debug
log_location STDOUTWith the knife.rb configuration file in place you should be able to view the clients known to the your Chef Server.
$ cd ~/Projects/chef/chef-repo
$ knife client listWhich should produce a list of all the nodes bootstrapped to that Chef Server.
Chef cookbooks can and do have dependencies on other cookbooks. Berkshelf manages those dependencies in much the same way Gem dependencies are managed by bundler for Ruby. In order to use Berkshelf to deploy to our production Chef Server you will need to configure it. Run the following command to create a default Berkshelf configuration:
$ berks configureYou will be prompted to provide several pieces of information.
$ berks configure
Enter value for chef.chef_server_url (default: 'http://localhost:4000'): https://path.to.your/chef-server
Enter value for chef.node_name (default: 'Ruby.local'): your-id
Enter value for chef.client_key (default: '/etc/chef/client.pem'): /Users/you/.chef/you.pem
Enter value for chef.validation_client_name (default: 'chef-validator'): chef-validator
Enter value for chef.validation_key_path (default: '/etc/chef/validation.pem'): /Users/you/.chef/chef-validator.pem
Enter value for vagrant.vm.box (default: 'Berkshelf-CentOS-6.3-x86_64-minimal'):
Enter value for vagrant.vm.box_url (default: 'https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box'):
Config written to: '/Users/you/.berkshelf/config.json'The result of this configuration will be a config.json file stored at $HOME/.berkshef
{
"chef":{
"chef_server_url":"https://path.to.your/chef-server",
"validation_client_name":"chef-validator",
"validation_key_path":"/Users/you/.chef/chef-validator.pem",
"client_key":"/Users/you/.chef/you.pem",
"node_name":"you"
},
"cookbook":{
"copyright":"Your Name",
"email":"you@example.com",
"license":"reserved"
},
"allowed_licenses":[],
"raise_license_exception":false,
"vagrant":{
"vm":{
"box":"Berkshelf-CentOS-6.3-x86_64-minimal",
"box_url":"https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box",
"forward_port":{},
"network":{
"bridged":false,
"hostonly":"33.33.33.10"
},
"provision":"chef_solo"
}
},
"ssl":{
"verify":true
}
}You can edit your config.json to add the additional information shown in the example above. (The initial file will be compressed into a single line, you will have to had line breaks to achieve the format shown above.)
For more information on Berkshelf, visit [http://berkshelf.com]
I use Berkshelf to create cookbooks as it manages cookbook dependencies automatically. This is especially useful when uploading cookbooks to a Chef Server.
Create a new cookbook like so:
$ berks cookbook <new_cookbook_name>While the knife command, through its configuration, will put new cookbooks it creates in the cookbooks directory of the parent chef-repo where it is run, the berks cookbook command will create the new cookbook in the directory that currently has focus. Therefore it is suggested that you change your working path to be ~/Projects/chef-repo/cookbooks before issuing the berks cookbook command.
When you created the chef-repo directory it came with a .gitignore file. While the chef-repo could be turned into a Git repository I choose not to do this. Each cookbook I create is its own Git repository, and nesting Git repositories is cumbersome. Through use of the Berksfile included with each cookbook created via berks cookbook it is possible to reference cookbooks outside of the immediate context; cookbooks from Github and other locations on your workstation..
Berkshelf will look in the current working directory for a .berkshelf/config.json file so I have leveraged this to work with multiple Chef Servers. Currently I have three Chef Servers that I work with.
Here is a very high-level overview of how to manage multiple Chef Servers via Berkshelf.
$ cd ~/Projects
$ mv chef alpha-chef$ mkdir -p ~/Projects/beta-chef
$ mkdir -p ~/Projects/gamma-chef$ cd ~/Projects/beta-chef
$ wget http://github.com/opscode/chef-repo/tarball/master
$ tar -zxf master
$ mv opscode-chef-repo* chef-repo
$ rm master
$ cd ~/Projects/gamma-chef
$ cp -R ../beta-chef/chef-repo .For each Chef Server you will have a pair of keys, your *.pem file and the Chef validator.pem file. Place your pem file and the validator.pem for that server in your ~/.chef directory. Be careful to name the files differently for each server so as not to overlay existing pem files.
For example:
$ cd ~/.chef
$ ls -al
drwxr-xr-x 10 mhn staff 340B Jan 7 14:11 ./
drwxr-xr-x+ 77 mhn staff 2.6K Mar 2 21:44 ../
-rw-r--r-- 1 mhn staff 1.6K Jan 7 14:08 alpha-chef-validator.pem
-rw-r--r-- 1 mhn staff 1.6K Jan 7 14:08 beta-chef-validator.pem
drwxr-xr-x 500 mhn staff 17K Feb 16 11:03 checksums/
-rw-r--r-- 1 mhn staff 1.7K Jan 7 14:11 gamma-chef-validator.pem
-rw-r--r--@ 1 mhn staff 1.6K Jan 7 14:09 mhn-alpha.pem
-rw-r--r-- 1 mhn staff 1.6K Jan 7 14:05 mhn-beta.pem
-rw-r--r-- 1 mhn staff 1.6K Jan 7 14:06 mhn-gamma.pem
drwxr-xr-x 3 mhn staff 102B Jan 7 14:09 pub/$ cd ~/Projects/beta-chef/chef-repo/.chef
$ cp ~/Projects/alpha-chef/chef-repo/.chef/knife.rb .
$ cd ~/Projects/gamma-chef/chef-repo/.chef
$ cp ~/Projects/alpha-chef/chef-repo/.chef/knife.rb .Edit the two new knife.rb files and fill in the correct pem file names.
$ cd ~/.berkshelf
$ mv config.json alpha-config.jsonRun the berks configure command once for each additional Chef Server, filling in the appropriate values. After each berks configure command rename the resulting config.json file appropriately. Afterwards your ~/.berkshelf directory will look similar to:
$ cd ~/.berkshelf
$ ls -al
drwxr-xr-x 11 mhn staff 374B Mar 2 00:39 ./
drwxr-xr-x+ 77 mhn staff 2.6K Mar 2 21:55 ../
-rw-r--r-- 1 mhn staff 815B Mar 2 00:16 alpha-config.json
-rw-r--r-- 1 mhn staff 815B Mar 2 00:16 beta-config.json
drwxr-xr-x 118 mhn staff 3.9K Jan 28 14:08 cookbooks/
drwxr-xr-x 5 mhn staff 170B Nov 13 13:20 default/
-rw-r--r-- 1 mhn staff 811B Mar 2 00:15 gamma-config.json
drwxr-xr-x 512 mhn staff 17K Feb 28 14:04 tmp/
drwxr-xr-x 6 mhn staff 204B Nov 13 09:56 vagrant/Berkshelf looks for a .berkshelf/config.json in the current working directory. We can use this fact to setup each chef repo with its own berkshelf config. Copy the files created above (alpha-config.json, beta-config.json, and gamma-config.json) into alpah-chef/chef-repo/.berkshelf/config.json, beta-chef/chef-repo/.berkshelf/config.json, and gamma-chef/chef-repo/.berkshelf/config.json respectively.
cd ~/.berkshelf
mkdir ~/Projects/alpha-chef/chef-repo/.berkshelf/
mkdir ~/Projects/beta-chef/chef-repo/.berkshelf/
mkdir ~/Projects/gamma-chef/chef-repo/.berkshelf/
cp alpha-config.json ~/Projects/alpha-chef/chef-repo/.berkshelf/config.json
cp beta-config.json ~/Projects/beta-chef/chef-repo/.berkshelf/config.json
cp gamma-config.json ~/Projects/gamma-chef/chef-repo/.berkshelf/config.jsonThe added complexity of managing multiple sets of knife and Berkshelf configurations, multiple sets of pem files, and multiple chef-repo, there is the possibility of inadvertently working against the wrong server. Caution should be exercised.
If you've successfully gotten this far you should now have configured your workstation to work with one or more Chef Servers. You should have knife and Berkshelf configurations for each Chef server, and you should have a working space for each server with a chef-repo to organize your work.
February 04, 2014 | posted in: nerdliness
My website uses Mint as a visitor tracking system. One of the Peppers (as plug-ins are called) displays errors; 404 being the primary culprit.
Last night someone manged to get a 404 trying to visit my posting about my tmux
Configuration. Only
instead of the date portion of the URL being 2013/09/05 it was 2013/09/06. I was curious if
perhaps I'd referenced that posting myself and had gotten the URL wrong. A quick Google search
showed me how to use grep to show all occurrences of a string in a set of files.
Here's the command template:
$ grep -rnw 'diretory' -e "pattern"
-r makes the command recuse through all files, -n causes the line number to be displayed, and
-w matches against the whole word. There are two optional parameters, --exclude and --include
that can be used for more efficient searching. E.g.,
$ grep --include={*.md,*.markdown} -rnw 'directory' -e "pattern"
Or you could exclude things to improve search efficiency.
$ grep --exclude=*.o -rnw 'directory' -e "pattern"
So in my case I ran this command from the root of my Jekyll installation.
$ grep -rnw _posts -e "2013-09-06"
And got no results. For comparison I ran this command.
$ grep -rnw _posts -e "2013-09-05"
_posts/2013-09-05-my-tmux-configuation:4:date: 2013-09-05 09:31
The single result shows the only occurrence of that date string is on line 4 of the posting itself, in the YAML header.
So not only do I know that the 404 was the fault of the visitor I also know how to rapidly search a
directory of files for a string using grep.
February 03, 2014 | posted in: nerdliness
Recently, after updating my installed brews, I wanted to see a list of dependencies for each installed brew. Homebrew provides a couple of useful commands to show dependencies.
You can see the dependencies for a given brew by running the brew deps command.
$ brew deps osxfuse
autoconf
automake
gettext
libtool
You can also ask brew to tell you which brews use a particular formula with brew uses --installed.
$ brew uses --installed autoconf
automake fuse4x htop-osx osxfuse sshfs
The --installed parameter is important, without it the results will be all brew formulas,
installed or otherwise.
Both of these are useful commands but I wanted a way to list all installed brews along with their dependencies. This is the "one-liner" I came up with after some experimentation.
$ brew list | while read cask; do echo -n $fg[blue] $cask $fg[white]; brew deps $cask | awk '{printf(" %s ", $0)}'; echo ""; done
The color specifications here are for zsh. If you want to use this command on bash it would look
like this.
$ brew list | while read cask; do echo -n "\e[1;34m$cask ->\e[0m"; brew deps $cask | awk '{printf(" %s ", $0)}'; echo ""; done
Here is a sample of the output.
$ brew list | while read cask; do echo -n $fg[blue] $cask $fg[white]; brew deps $cask | awk '{printf(" %s ", $0)}'; echo ""; done
apple-gcc42
autoconf
automake autoconf
cscope
faac
ffmpeg faac lame pkg-config texi2html x264 xvid yasm
fontconfig freetype libpng pkg-config
freetype libpng
fuse4x autoconf automake fuse4x-kext gettext libtool
fuse4x-kext
gettext
git
giter8
glib gettext libffi pkg-config xz
gnu-go
htop-osx autoconf automake libtool
imagesnap
jenkins
lame
libdvdcss
libevent
libffi
libgpg-error
libiconv
libksba libgpg-error
libpng
libtool
libxml2
libxslt libxml2
libyaml
macvim cscope
mercurial
mtr pkg-config
ngrep
openssl
ossp-uuid
osxfuse autoconf automake gettext libtool
pkg-config
popt
readline
reattach-to-user-namespace
sbt
scala
sqlite readline
sshfs autoconf automake gettext glib libffi libtool osxfuse pkg-config xz
szip
texi2html
tig
tmux libevent pkg-config
vim
wget openssl
x264 yasm
xvid
xz
yasm
youtube-dl
And here is a screen shot showing the colors.
