Skip to content

Instantly share code, notes, and snippets.

@mxmeinhold
Last active April 1, 2021 00:36
Show Gist options
  • Save mxmeinhold/df6ac59122911c138425fbad33535814 to your computer and use it in GitHub Desktop.
Save mxmeinhold/df6ac59122911c138425fbad33535814 to your computer and use it in GitHub Desktop.
Shell Snippets

Snippets

A collection of assorted shell snippets and other useful bits. Some of these are shell specific (I use bash), so copy paste at your own risk.


The directory stack (pushd, popd, dirs)

Bash has a directory stack. This can be used to suplement cd -, since it goes deeper than just the previous directory. See man 1 bash for the full set of options.

pushd <dir> changes directory to <dir>, and pushes the old working directory onto the stack. It then prints the stack (note that the first element in the printed stack is always the current directory). popd pops the first directory off the stack, and changes to the next directory dirs prints the current stack

You can also use dir -c to clear the stack.

Here's a short example

$ pwd
/etc
$ pushd /var
/var /etc
$ pwd
/var
$ pushd /
/ /var /etc
$ pushd /var/log
/var/log / /var /etc
$ dirs
/var/log / /var /etc
$ popd
/ /var /etc
$ popd
/var /etc
$ popd
/etc
$ popd
bash: popd: directory stack empty

Job management, aka Running tasks in the background (fg, bg, jobs, wait)

In bash, I know of 2 ways to run a command in the background:

  • Suspend a running process with the suspend charachter (typically ctrl-z) or the delayed suspend charachter (typically ctrl-y) (suspend when it tries to read input from the terminal), then resume it in the background with bg
  • Execute a command with a trailing & (e.g. long-running-task &)

Both of these will leave you with a usable shell, but your task will still be running. It won't use stdin of your shell (if it asks for input it will most likely hang), but it will use stdout, so you might want to use quiet flags if you don't want it randomly printing.

When you put a job in the background, the shell will print something like [1] 25647. This indicates that the job you just started (or resumed) is job 1, and the id of the last process in the pipeline is 25647.

Typing fg will bring the top job into the foreground. You can resume a specific job. To resume job 1, you'd use fg %1 or just %1. This syntax can also be used to resume a suspended task in the background, bg %1 or %1 &.

jobs will list the state of all jobs. wait will cause the shell to wait for all the running jobs to change state.

An example use case:

# Run `do_command` on every server, in parallel (mostly)
for host in host{001..100}.example.com; do (ssh $host "do_command") & done

# Wait for all of the ssh processes to exit (or at least change state) before resuming the shell
wait
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment