Intro to the Command Line: Part II
Intro to The Command Line (Part II)
From April 1, 2014
Linux has a set of "virtual consoles". Try pressing "Ctrl-Alt-1"; you should see a text login screen (aka virtual console). Now press "Ctrl-Alt-2"; you'll see another virtual console. You can press "Ctrl-Alt-7" to get back to the desktop GUI (the graphics environment runs on its own virtual console).
What other keyboard shortcuts are available? Keyboard shortcuts are present at (at least) three levels. First, we have shortcuts that are present regardless of whether or not you're running a GUI. Virtual console switching is one example. Ctrl-Alt-Delete is another. (Yes, the three-fingered salute works in Linux too).
Second, there are shortcuts from the graphics environment. For example, Alt-TAB to switch programs. Your desktop should have a way to list (and change) the set of keyboard shortcuts it provides.
Finally, there are shortcuts particular to individual programs. Since we're talking about the command line, we'll focus on keyboard shortcuts available at the terminal.
$ stty -a speed 38400 baud; rows 40; columns 85; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; ...
The stty command prints terminal settings, and I've shown some of its output above. "kill = ^U" shows one of the keyboard bindings. "^U" is shorthand for Control-U, and "kill" means "remove all characters to the left of the cursor." Try typing some stuff at the command line, then press Ctrl-U; the entire line should be deleted.
The shell also provides its own set of keyboard shortcuts. Here are some useful keyboard shortcuts for bash:
- up and down arrows cycle through command history
- Ctrl-F and Ctrl-B move forward and backward by one word
- Ctrl-A moves the cursor to the beginning of the line
- Ctrl-E moves the cursor to the end of the line.
- Ctrl-L clears the screen.
To find others, have a look at the "READLINE" section in man bash.
Linux has two programs to help you find files on your hard drive: find and locate.
Find works by examining files as the command is run; locate relies on a per-built database of file names (most linux distributions include a cron job to update locate's database).
Here a few commands to try
find /etc/ find /etc/ -type f find /etc/ -type d
The first command shows all files and directories in /etc. The second shows all regular files under /etc. The third shows all subdirectories under etc.
You'll likely see a few lines that look like this
find: `/etc/ssl/private': Permission denied
Here, find is saying "you don't have permission to look in /etc/ssl/private", and we can use ls to verify that find is correct
$ ls -ld /etc/ssl/private 4 drwx--x--- 2 root ssl-cert 4096 Apr 26 2013 /etc/ssl/private/
Notice that this directory is owned by root, and only root has the "r" permission bit.
Here's another command to try
find /etc/ | head -10
This is an example of a pipeline. When you see a pipe character ("|") this means that the output of the command on the left is fed ("piped") to the command on the right. We've already seen what find /etc does; head -10 is a command that prints the first 10 lines of input, and discards the rest. By combining the two, we get a listing that contains ten files.
Here's another example of a pipeline
find /etc/ | grep mlocate
Now, we're taking find's output and feeding it to grep mlocate. Grep is a pattern matching command. In this case, grep reads the output of find, and prints lines that contain "mlocate". You should see one file that meets this condition
We'll return to this file in a moment.
grep can also find patterns inside of files. For example
$ grep www /etc/group
examines the file "/etc/group", and prints lines containing "www".
A look at /etc/cron.daily/mlocate
/etc/cron.daily/mlocate is a cron job: a script that's run on a schedule. ("cron" is the name of the linux service that runs scheduled jobs).
Let's look at the contents of this file
mlocate is a "shell script"; a set of commands that are placed in a file, and executed by a shell. Let's spend a few moments dissecting this script:
The first line of every script is special: it specifies which interpreter runs the file. Here, we see that the interpreter is /bin/bash. The operating system actually run this script as "/bin/bash /etc/cron.daily/mlocate".
set -e tells the shell that it should exit immediately if any scripted command fails.
[ -x /usr/bin/updatedb.mlocate ] || exit 0
This line deserves a little bit of discussion. The "||" is pronounced "or"; it means "run the commands separated by || until one of them succeeds". The shell runs "[ -x /usr/bin/updatedb.mlocate ]"; if that succeeds, then the shell will skip the rest of the command line. On the other hand, if that command doesn't succeed (i.e., there's no updatedb.mlocate executable), then the shell runs "exit 0" (which ends the script).
"[" is actually a program, and you can see it with "ls /usr/bin/[". Do "man [" to see what it does. The "[" command is called "test".
The next block contains a set of "if statements".
if which on_ac_power >/dev/null 2>&1; then ON_BATTERY=0 on_ac_power >/dev/null 2>&1 || ON_BATTERY=$? if [ "$ON_BATTERY" -eq 1 ]; then exit 0 fi fi
The general format is "if CONDITION; then SOME-COMMANDS; fi". ("fi" ends the "if" statement"). Our condition is "which on_ac_power >/dev/null 2>&1". There's a lot happening in that statement, so let's take it piece by piece.
- on_ac_power is a program. It exits with a success code when your computer is running on ac power, and exits with an error code when your computer is running on batteries.
- "which on_ac_power" finds the full path to the on_ac_power command. (Try typing "which on_ac_power" into the terminal, and see what happens). Essentially, this checks to see if the on_ac_power command is installed on your system.
- ">/dev/null". Sends the output of "which on_ac_power" to /dev/null (which throws the output away). That makes sense in this case, because we don't care about the output of the command, we're only interested in whether it succeeds or fails.
- "2&>1". This means "send the output of file descriptor 2 to whereever the output of file descriptor 1 is going". File descriptor 2 is called "stderr"; this is a program's error stream. File descriptor 1 is called "stdout"; this is a programs normal output stream. ">/dev/null" tells the shell to discard the standard output stream and ">/dev/null 2&>1" tells the shell to discard standard error too.
This general name for ">" is "redirection". The bash manual page has a section ("REDIRECTION") devoted to redirection operators.
As a whole, this set of if statements is saying "see if we're on battery power, and if so, exit". In other words, don't run this job if we're running on battery power.
Lines starting with "#" are comments.
This line is a variable assignment which gives the variable LOCKFILE the value "/var/lib/mlocate/daily.lock". With that assignment, we can use "$LOCKFILE" (the variable) in place of the actual value.
if [ -e "$LOCKFILE" ]; then echo >&2 "Warning: $LOCKFILE present, not running updatedb." exit 1 else touch "$LOCKFILE" fi
The block of code above ensures that only one copy of mlocate is running at any given time. If the "$LOCKFILE" exists, then print a warning and stop. Otherwise, create the lockfile and continue.
# See ionice(1) if [ -x /usr/bin/ionice ] && /usr/bin/ionice -c3 true 2>/dev/null; then IONICE="/usr/bin/ionice -c3" fi
This sections checks to see if the ionice program is installed. If so, we'll use it to reduce the priority of mlocate's I/O operations (so we don't completely hog the disk).
The last line is where all the work is done. updatedb.mlocate builds the file database for locate. Essentially, this command runs find on the entire filesystem, and generates an index of the files that find finds.