In the last part, we learned how to navigate the Linux file system. The set of commands we learned there are the most common commands that terminal users take advantage of. Now that we can navigate around the Linux file system let’s get into some management stuff.

Package Managers

After navigating the file system, the most essential kind tool available to you in Linux are package managers. A package manager is a tool that allows you to download more tools, and every family of distros has its own version. For Alpine, we have apk, and it presents a new Linux concept to us: subcommands.

When it comes to commands and the terminal, some of them have so much functionality that they split themselves up into smaller ones. Take package managers, for example. When it comes to managing packages, there are a few tasks that might need to be done. Some common cases are installing a new package or removing one we don’t want. While each subcommand of apk is related to each other one in some way, they act as if they were their own command altogether. We can call a command that has subcommands a parent command, or a super command. Each command may or may not have subcommands, and the subcommands that exist are unique to that parent command, regardless of the name. For example, two other package managers, apt and dnf both have the subcommand install; however, the functionality is different between them.

For apk, we care mostly about the add and del subcommands. The add subcommand downloads and installs a a specified package. The del subcommand uninstalls an installed package. To use either one, you can run apk add X or apk del X, where X is the package to install. As practice, we’ll download a package called tree, which gives us the tree command.

The tree command extends off of the ability of ls by providing us with a beautiful text-based representation of the current directory and all directories within it, recursively, and it isn’t installed by default in Alpine. To properly show off tree, it would be useful to set up some files and directories to output. Run the following commands:

touch file1.txt file2.txt file3.txt
mkdir subdir
mkdir subdir2
cd subdir
touch subfile1.txt subfile2.txt
cd ..
cd subdir2
touch subfile3.txt subfile4.txt
mkdir subsubdir
cd subsubdir
touch subsubfile1.txt
cd ~

Now that we have a sufficient group of files, let’s download the tree package to get the tree command with apk add tree:

Now if we run tree, we will get a nice list of everything we just made:

There are a lot of packages that can be installed, and it can be challenging to keep track of all of their names. Typically it goes like this: you have some functionality that you want in Linux, you google it, and somebody tells you what package to install. That’s the usual way of doing things, but if you would like to see everything available to be installed by apk, check out the Alpine package registry.

Creating a User

So far, we’ve been signed in as the root user. In Linux, the root user acts as the administrator. They can do whatever they’d like to almost any file or directory. It’s pretty bad practice to use root all the time as we have been. Instead, most people who use Linux have separate users that can temporarily switch to the root user when a command requires it. To follow that convention, let’s create a user using the adduser command. To use it, run adduser X where X is the name of the user to create and enter a password for the user when prompted:

Important note: On most distros, the equivalent command is useradd. Alpine strays a little off the road on this one from most systems, although I prefer adduser. While adduser prompts you to set the password immediately, useradd does not, and you must do so separately using the passwd command. On any distro, if a user’s password needs to be changed for any reason, you can use the passwd command. To use it, you must be signed in as either root or the user whose password you want to change, and run passwd X, where X is the user.

The user is created, and their password is set, but the account is not ready for use. If we were to use the account right now, we could only use commands that don’t require root access. As I mentioned earlier, the root user has access to almost all files and directories, allowing them to use any command. Any other user we create will only have access to their home directory by default, which isn’t much. Commands that manage a system such as apk need to modify files and folders outside of a typical user’s home directory. This requires us to sign into root when we want to install a package.

We can take advantage of an incredibly popular and powerful tool called sudo to allow us to temporarily switch to root to run specific commands as a different user. The sudo command is not installed by default on Alpine, but we can use apk to solve that. To do so, run apk add sudo. To give a user permissions with sudo, we are required to run a command called visudo, which uses a terminal text editor called vi. vi is an incredibly powerful text editor and can be used for a large variety of tasks, but it’s a bit complicated to start with. Since I don’t want it to distract from learning Linux just yet, I’ll create a separate post on the beauties of the vi and vim commands. Instead, for now, we’ll install a more straightforward editor to use called micro.

Unfortunately, micro can’t be installed by apk by default. apk can access many packages, but to keep things simple, it only gives you access to one repository. A repository is simply a collection of packages, and the default apk repository is the “stable” repository. The packages in it have somewhat of a guarantee that they won’t break on you. To download micro, we need to allow apk to grab from an “edge” repository called “testing”. An edge repository contains packages that are bleeding edge and relatively new but are not considered stable, and “testing” is just a category of edge. Basically, they’re “use at your own risk” packages. To add such a repository, we need to modify the contents of /etc/apk/repositories. Fortunately, we learned how to do this in the last part, so let’s get to it!

First, let’s navigate into /etc/apk with the cd command. If you use ls, you’ll see that there’s a regular file called “repositories”. This file is a list of all the repositories that apk can access. Use the cat command to get the contents of it. You should see about five lines of web URLs, some of them beginning with a pound symbol. Any lines that begin with the pound symbol are “commented”, and are therefore ignored by the file. One of the commented lines is the main edge repository and is the one we want. To identify it, look for the line that has the suffix “edge/testing”. To enable it, we just need to add a line to the file that contains the uncommented version of that line (the line minus the beginning pound sign). As we did in the last part, we can use echo and redirects to do that, but while we previously used the > symbol, we need to use the >> symbol this time. The difference is that while the former would replace the target file with the output of the redirected command, the latter will just add it to the end of the file. Here’s what the process looked like for me:

Finally, we can run apk add micro to get it installed! That was a lot of work, and we took a bit of a detour, but now we have a simple editor that we can use with visudo. To tell visudo that we’d like to use micro, run export VISUAL=micro. That line sets an environment variable, and it’s something we’re going to cover later in this part. As a quick explanation, environment variables are, in a way, how you set settings in the terminal.

Now we can run visudo, and micro is used to open the file to edit. In micro, you can use the arrow keys to move around. At the bottom of the file, add the line: X ALL=(ALL) ALL, where X is the name of your user. Here’s what my file looks like:

The line that we added tells sudo that for our user, we want them to be able to run any command that they’d like with it. To save the file, press CTRL-s, and to quit, press CTRL-q. Now everything is set up for our user! We can log into the account with the login command, which provides us with the same interface we see when we reboot the machine. Type in the username and password to log in.

Finally, to verify that we’re logged in correctly, run the whoami command, which outputs the name of the current user. You can also use pwd to see that your working directory has changed to the new user’s home directory.

The sudo Command

Try to access the root user’s home directory by running this command: ls /root. You should see something like ls: can't open '/root': Permission denied. Now try to run apk del tree. You should get two lines of output, both starting with “ERROR” and both ending with “Permission denied”.

In Linux, every file is owned by some user. If a user tries to access a file that they don’t own, they will get an error. The commands above involve accessing directories that the user we’re signed in as don’t have access to, and therefore, we get a specific error: Permission denied. However, as I mentioned before, one user can bypass any permission errors: root. To temporarily switch to the root user, all we need to do is put the sudo command before any other command we want to run as root. Try doing that with the commands from above:

Nice! No errors. That’s really all there is to using the sudo command. Just put it before a command you’d like to run as root! Be careful, though. With the root user’s permissions comes great responsibility. You can do a lot of messy stuff with sudo, and you can destroy some pretty important files or directories if you’re not careful. Permissions are put in place for a reason!

Environment Variables

Environment variables are /very/ important. They are most often used as settings for commands and are incredibly powerful. Not only that, but they’re also a simple concept! All an environment variable is, is a word with a text value associated with it.

Let’s take a concept that we’ve run into a lot: a user’s home directory. How does Linux know where a user’s home directory is, where is it stored, and how can we access it? The answer to any of those questions is environment variables, and its name is HOME (case-sensitive). To get the value of an environment variable, we can run echo $X, where X is the name of the environment variable. Try it with $HOME:

We can also set the value of an environment variable. To do so, run X="Y", where X is the name of the environment variable, and Y is the value. To test this, create a directory in your home directory called new-home. Now, to make this new directory your home, run HOME="/home/X/new-home", where X is your username. If you echo the HOME variable again, you should see that it’s different. Now, if you run cd ~, you should go to the new directory you made, like so:

But what if you want to go back to what home used to be? You can handle this in two ways. Either you can just set home to be what it was before manually, or just log out and log back in (using the exit command). The reason the second option works is because every time you set an environment variable, it only lasts for as long as you are logged in as that user. If you want to persist the value of an environment variable, you’ll have to set it every time you log in. However, there are ways to automate this that we’ll see momentarily.

In Linux, the most important environment variable is $PATH. Almost every command that we’ve used so far is a runnable program, and that is the most common type of command. Since they are all just programs, they have to be stored somewhere, and how does Linux know where to check where a command is when you enter one? It can’t scan the whole filesystem to every time you want to run something, otherwise working in the terminal would take forever. Instead, Linux has a set list of directories that it will search through until it decides it can’t find the command, and those directories are set in $PATH. Use echo to find them:

Notice that the output is a list of paths separated by a colon. If you try to use a command that isn’t in one of those directories, the terminal can’t run it unless we specify the absolute path to it. Fortunately, we can easily add on that list with this command: PATH=$PATH:/our/absolute/path. In that command, we set $PATH equal to itself, with the addition of a colon and our new path. This will add it to the list of paths for Linux to search when we run a command. This is especially useful to do when you download a program from the internet. While apk puts the downloaded binaries into /usr/bin (which is in your path by default), downloading things manually will not. You can still use the command by providing the absolute path to it every time, but that’s obnoxious. Instead, we can add the directory the program resides in, then we can just call the command directly.

As I mentioned before, if you want to persist the value of an environment variable, you need to set it every time that we log in. Fortunately, in Alpine, each user has a file that they can specify a list of terminal commands to run as soon as they log in. That file is located at ~/.profile. If it doesn’t exist, use touch to create it. We can use micro to modify the data by running micro ~/.profile. Enter a line in that file to change any environment variable like so, then use CTRL-s and CTRL-q to save and quit:

Quick note: putting the “export” keyword before setting an environment variable tells the terminal that other commands should see the change too. Otherwise, only you have access to the change. In most cases, you want to add the export keyword.

If you run sudo reboot and log back into the account, you can echo the variable and see that it has the change you made in ~/.profile.

Good job for getting this far! In the next and final part, we’ll learn what a shell is, what to expect on other families of distros, and how to unlock the real power of commands. Click here if you’re ready.