Universal Install Script by XKCD – Combat test

Several days ago, I was gazing at the Universal Install Script comic by Randall Munroe, wondering if he may not have solved all the world’s problems, save for the usual famine, war, poverty, education, corruption, and so on. But there’s a certain appeal to having THE one script to rule them all, and in BASH-ness bind them. Yes, I was bored, so I thought, let’s try it out.

This is going to be my attempt to run the Universal Install Script (UIS), not to be confused with the Unwarranted Self-Importance Syndrome, an affliction of many an Internet user, and then modify the script so it works smoothly, elegantly and without errors. Safely too. Let us.

The original (sin)

As conceived by Randall Munroe, UIS is a series of commands, executed one after another, invoking a bunch of package managers and other associated tools, all in order to help you install whatever is the first argument of your script. Hence $1. In the tooltip, he recommends using the -y flag and redirecting errors to /dev/null to minimize noise. I can agree with the latter, but answering Yes blindly to a whole bunch of system commands is probably not a task for the fainthearted. Oh yes, in the best fashion of those sub-100-IQ TV shows, don’t do this at home!

universal_install_script

First attempt

I decided to use the script without modifications, only addition the STDERR redirection. To wit:

#!/bin/bash

pip install "$1" 2>/dev/null
easy_install "$1" 2>/dev/null
brew install "$1" 2>/dev/null
npm install "$1" 2>/dev/null
yum install "$1" 2>/dev/null
dnf install "$1" 2>/dev/null
docker run "$1" 2>/dev/null
pkg install "$1" 2>/dev/null
apt-get install "$1" 2>/dev/null
steamcmd +app_update "$1" validate 2>/dev/null
git clone https://github.com/"$1"/"$1" $1 2>/dev/null
cd "$1"; ./configure; make; make install 2>/dev/null
curl "$1" | bash 2>/dev/null

exit 0

You old git!

I started by running the tool as a non-root user. Most of the commands fail, which is fine. The git pull will definitely work, and it will prompt you for your user name and password in an interactive fashion. Failing that, you will be able to provide the username/password on the command line.

GitHub prompt

Git error

Git CLI prompt

But it sure is distracting, and having a window prompt pop up is sort of a big flaw in the UIS logic. So I decided to comment out the git command.

#git clone https://github.com/"$1"/"$1" $1 2>/dev/null

Second attempt

My next obstacle was the cd shell builtin and the attempt to compile. If the directory does not exist, then you will be seeing a lot of noise on the command line, and again, this is not something we want. So I decided to add a little bit of sanity check logic — I know, it defeats the purpose of what UIS stands for, but it helps get a cleaner output.

[ -d "$1" ] && bash -c 'cd "$1"  ./configure; make; make install 2>/dev/null'

Third attempt

Now, the script was ready to run — as sudo. This is the tricky bit, but not really. However, there’s quite a bit of activity happening, much more so than our first attempt. This is why I chose not to background the commands, as they have different run times and prompts, and it actually makes sense to serialize them and be able to see what they are doing.

I started with VLC, and encountered some package conflicts, although they had nothing to do with the script per se. Then I tried Transmission and it installed just fine. After a few more attempts and some extra games, I was convinced that UIS was working well and causing no harm.

sudo transaction 1

sudo transaction 2

I did have some unwanted extras, but that’s fine. After all, the purpose of the UIS is to solve all problems for us, and the price we have to pay is having some extra packages on your hard disk. I couldn’t find any other obvious caveats.

Final version

This is what it sounds like when doves cry:

#!/bin/bash

pip install "$1" 2>/dev/null
easy_install "$1" 2>/dev/null
brew install "$1" 2>/dev/null
npm install "$1" 2>/dev/null
yum install "$1" 2>/dev/null
dnf install "$1" 2>/dev/null
docker run "$1" 2>/dev/null
pkg install "$1" 2>/dev/null
apt-get install "$1" 2>/dev/null
steamcmd +app_update "$1" validate 2>/dev/null
#git clone https://github.com/"$1"/"$1" $1 2>/dev/null
[ -d "$1" ] && bash -c 'cd "$1" ./configure; make; make install 2>/dev/null'
curl "$1" | bash 2>/dev/null

exit 0

Conclusion

UIS is an interesting little thing, and the most interesting thing about it is that it works. I am sure lots of you have already created various wrapper scripts for yourself, things to speed up system updates or maintenance. Essentially, apart from the obvious fun intent embedded in its lines of text, UIS delivers a decent experience wherever you go. In other words, it’s a portable system updater. It aligns with my vision of Linux professionalism, and the use of meta, human-readable packages to deliver content to users.

Now, if you really want to have a truly robust and seamless experience, you will need to start adding lots of sanity checks, including checking for the installation path for package managers themselves, and then installing them if necessary, fixing broken indexes, cleaning and pruning and refreshing repo data, and other cool things. And then you realize you’re inventing a package manager of your own. Perhaps you should. ‘Tis the thin line of the wedge, but that’s how it starts. UIS for president.

On an ever so slightly more serious note, you might want to try this on a non-production system, and then evolve the script as you see fit. Perhaps you could create update scripts (UUS), or maybe search scripts (USS), or even removal scripts (URS). And then, you can … Damn, we’re reinventing Linux. Stop, just stop. Enjoy your escapades, fellas.


Cover Image: Universal Install Script by Randall Munroe at XKCD.

  • http://blog.olansa.co.uk David Harrison

    Hmm. A couple more serving suggestions…

    apk add “$1” 2>/dev/null # alpine
    xbps-install -S “$1” 2>/dev/null # void
    pacman -S “$1” 2>/dev/null # arch
    emerge “$1” 2>/dev/null # gentoo
    urpmi “$1” 2>/dev/null # mandriva
    choco install “$1” 2>/dev/null # :)
    install-package “$1” 2>/dev/null # :(

    • Hisashi Kadoyama

      There also needs to be a “Linux or bsd” detection if then statement so as to handle pkg.

      If no pkg, don’t run pkg installation.

      The lack of logic implies the need for a multi line command using && and .

      • http://blog.olansa.co.uk David Harrison

        Fine with me. Please chuck one in there then. :)

    • sv

      zypper install “$1” 2>/dev/null # SuSE

  • Jeremy ****

    You don’t even need the [[ -d ]] check if you do a mkdir -p. In reality, you wouldn’t need this at all if you used && as a command separator for the git sequence instead of ; . The semicolon continues execution no matter the error state, whereas && will only continue execution when the previous command is successful. So in your case, you’re worried about the directory being created, but if the git clone command was successful in the first place, that has already happened.

    • Big Fatman

      “mkdir -p” doesn’t maky any sense to me. If there’s no directory in the first place, why would you create it, “cd” into it and attempt to run “./configure; make”?

      • Hisashi Kadoyama

        Cos that’s how git rolls.

  • Hisashi Kadoyama

    This is almost brute force as there are no detection of commands’ existences.

    Why should a command run if it never existed?

    • Jake Achée

      The idea is to eliminate thinking. “Oh, I need the python LDAP library. I’ll use `sudo uis python-ldap`. Done.”

      No worrying about what system you’re on, which package manager it uses this week, or anything. The commands that don’t exist, in the final version here, just generate bash errors that then get redirected to null.

      It’s quite elegant in its ugliness.

  • Dedoimedo

    He he, the debate is getting rather heated. I’m lovin’ it (lowercase).
    Dedoimedo

  • LamiaLove

    Wow, this is totally retarded.

  • Carlos Osuna

    The idea makes sense, but it won’t work in practice since very few “packages” have a standard name across platforms.

    Alas, now that Windows is being invited into the Linux party, many things are gonna change given the GUI nature of most Windows developers, contrasted with the CLI exclusiveness of most Linux hardliners.

    I could imagine a self contained file containing the script and some kind of manifest to describe what names are needed for each package manager.

    This could be fed into a /sh/wash shell (the Windows borne Again SHell) which would somehow decide if you need a UI or not using a clever use of VT100 escape sequences.

    My two cents.

  • Pagan_God

    I’m not that familiar with the vetting process for these various package managers, but aren’t you opening yourself up to installing malware using this script?

    • The Engineer

      Certainly not! Malware is things you don’t want to run, and as here you can clearly see we wanted to run it, whatever it is.