Bash special variables

This is more some kind of “note-to-self”, than a blog post.

All credit goes to the guys who answered this Stackoverflow question explaining different bash variables that we now and then need to look up again.

  • $1, $2, $3, … are the positional parameters.
  • "$@" is an array-like construct of all positional parameters, {$1, $2, $3 ...}.
  • "$*" is the IFS expansion of all positional parameters, $1 $2 $3 ....
  • $# is the number of positional parameters.
  • $- current options set for the shell.
  • $$ pid of the current shell (not subshell).
  • $_ most recent parameter (or the abs path of the command to start the current shell immediately after startup).
  • $IFS is the (input) field separator.
  • $? is the most recent foreground pipeline exit status.
  • $! is the PID of the most recent background command.
  • $0 is the name of the shell or shell script.
  • $_ last argument of last command
  • $* / $@ list of arguments passed to script as string / delimited list

Most of the above can be found under Special Parameters in the Bash Reference Manual. There are all the environment variables set by the shell.

For a comprehensive index, please see the Reference Manual Variable Index.


Xvnc versus X11vnc

What is the difference between Xvnc and X11vnc?

Xvnc: Is an X and VNC server at the same time. It is mainly used to run the X server on a virtual display, (in the absence of a physical one) and connect remotely to it with a VNC client/viewer.

X11vnc: Is a vncserver that “publishes” an existing physical X display over VNC, allowing remote clients to connect with it using a VNC viewer. That is, they can see the actual running desktop windows, as if they were in front of the server.

Bash ‘help’

Some commands you type in the shell are actually not binaries but shell (bash for example) buitins. For example, “alias” is such an shell builtin.

~# type alias

alias is a shell builtin

~# man alias

No manual entry for alias

In order to obtain more information about the “alias” builtin, you should type “man bash” and search what you are looking for in the hundreds of pages long man.

However, there is a quicker way! “help” helps you:

~# help alias

alias: alias [-p] [name[=value] … ]

    Define or display aliases.

    Without arguments, `alias’ prints the list of aliases in the reusable

    form `alias NAME=VALUE’ on standard output.

    Otherwise, an alias is defined for each NAME whose VALUE is given.

    A trailing space in VALUE causes the next word to be checked for

    alias substitution when the alias is expanded.    


      -p Print all defined aliases in a reusable format

    Exit Status:

    alias returns true unless a NAME is supplied for which no alias has been



Execute sudo from a cron script

Recently I bumped into this problem, and I wanted to share it’s easy solution:

Say you want to execute:

0 6 * * * /home/oraias/cron/


PID=$(ps aux | grep tomcat8 | grep -v grep | tr -s ” ” | cut -d” ” -f2)
kill -9 $PID
sleep 5
sudo systemctl start tomcat8

Each day at 6AM cron launches this script. It looks up the PID of a Java process with “tomcat8” in it’s argument list. Kills the process and starts it again. Since this script is being launched as a non-root user, sudo is required for systemctl operation (assuming you configured the sudoers file).

It might happen that the last line of the script silently fails. If this is also your case, check the following options in /etc/sudoers (make sure to open it with sudoedit):

# Disable “ssh hostname sudo <cmd>”, because it will show the password in clear.
# You have to run “ssh -t hostname sudo <cmd>”.
Defaults requiretty

# Refuse to run if unable to disable echo on the tty. This setting should also be
# changed in order to be able to use sudo without a tty. See requiretty above.
Defaults !visiblepw

Since cron doesn’t launch any TTY, the above options cause sudo to fail silently.

Comment out both to change this behavior.


4 years later

4 years have passed since my last post here. Oh yeah, I hear you thinking…that’s a loooong time. True, it is.

I have been doing a lot of different stuff in these last 4 years, I changed jobs, ended up in different projects, started a webshop (, got into Adwords, Analytics, marketing online, cloud computing and in the meantime also had another lovely daughter. Quite busy to be honest 🙂

Today seems like the perfect day to get back behind my keyboard and continue writing down those volatile snapshots of my mind 🙂


Yum provides…

Yum, the preferred RPM package manager makes our lives a bunch easier when you need to install new packages.
Below an example of a nice feature that yum “provides”.

[pieter@laptop ~] nslookup

bash: nslookup: command not found

[pieter@laptop ~] yum search nslookup
Loaded plugins: fastestmirror, langpacks, presto, refresh-packagekit
Loading mirror speeds from cached hostfile
Warning: No matches found for: nslookup
No Matches found

Doooooh!! Now what?

In Yum’s man page (man yum) we find our rescue:

provides or whatprovides

Is used to find out which package provides some feature or file. Just use a specific name or a file-glob-syntax wildcards to list the pack‐
ages available or installed that provide that feature or file.

[pieter@laptop ~] yum provides */nslookup

Loaded plugins: fastestmirror, langpacks, presto, refresh-packagekit
Loading mirror speeds from cached hostfile

32:bind-utils-9.8.1-2.fc16.x86_64 : Utilities for querying DNS name servers
Repo : fedora
Matched from:
Filename : /usr/bin/nslookup

32:bind-utils-9.8.2-0.2.rc1.fc16.x86_64 : Utilities for querying DNS name servers
Repo : updates
Matched from:
Filename : /usr/bin/nslookup

As we can see from Yum’s output, the package we need to install in order to have nslookup is “bind-utils”

[pieter@laptop ~] yum install -y bind-utils

[..output stripped…]

[pieter@laptop ~] nslookup
Server: ******
Address: *****#53

Non-authoritative answer: canonical name =


How to avoid commands being logged in bash history

Maybe if you are not a hacker it’s not very useful, and if you are a hacker you probably already knew this. But hey, just in case it might be useful, I’ll share it with the world.

Normally every command you write it the Bash command line gets recorded in it’s history.

A simple example showing that this is true

[pieter@laptop ~]$ echo “Hey, I’ll end up in the history”
Hey, I’ll end up in the history
[pieter@laptop ~]$ history
2 echo “Hey, I’ll end up in the history”
3 history
[pieter@laptop ~]$

The echo command is logged in the history, as well as the history command itself.

Now, if you do not want the command you execute to be logged in the history, set the following variable:

$ export HISTIGNORE="&:[ ]*:exit"

From now on every command you executed preceded with a space isn’t being logged to the bash history. Useful in case you need to execute a command that has a password as parameter (I know, not very secure…but still).

[pieter@laptop ~]$ [SPACE]echo “I remain unnoticed, hahahahaha”
I remain unnoticed, hahahahaha
[pieter@laptop ~]$ history
2 echo “Hey, I’ll end up in the history”
3 history