What’s the shell?

  • Multiple interfaces exist: GUIs, voice interfaces, AR/VR.
  • Graphical interfaces are limited.
  • For full control, use a textual interface: The Shell.
  • Platforms offer a variety of shells.
  • Introduction to “bash” (Bourne Again SHell).

Accessing the Shell

  • To start: you need a terminal.
  • A shell prompt is where you type commands.
# missing:$ ··································· bash
 

Using the shell

  • Typing a command at the prompt will execute it.
  • Arguments can be passed to commands.
# missing:$ ··································· bash
date

More Shell Commands

  • Commands are parsed by whitespace.
  • $PATH helps find executable programs.
# missing:$ ··································· bash
echo hello
# we expect hello

  • Understanding paths.
  • pwd shows the current directory.
  • cd changes directories.
  • Use ls to list contents.

Shell Permissions

# missing:$ ··································· bash
ls -l ~
  • Using mv, cp, mkdir.
  • The man command for manuals.

Connecting programs

  • Programs have input and output streams.
  • Redirection with < file and > file.
  • Using pipes | to chain commands.

More about Programs and Pipes

# missing:$ ··································· bash
ls -l / | tail -n1
  • Use of curl, grep, and cut.

A versatile and powerful tool

  • Understanding the “root” user.
  • The use of sudo for superuser actions.
  • Kernel parameters in sysfs.

A small break…


Job Control


Interrupting a Job

  • Need to stop lengthy commands, like a find command in large directories.
  • Common way: Ctrl-C.
  • How and why does this work?

Killing a process

  • Shell communicates via signals.
  • Signals act as software interrupts.
  • Ctrl-C sends a SIGINT signal to the process.

A Python script that captures SIGINT and ignores it.

#!/usr/bin/env python
import signal, time
 
def handler(signum, time):
    print("\nI got a SIGINT, but I am not stopping")
 
signal.signal(signal.SIGINT, handler)
i = 0
while True:
    time.sleep(.1)
    print("\r{}".format(i), end="")
    i += 1

  • Sending SIGINT to above program will not stop it.
  • SIGQUIT (by typing Ctrl-\) can be used instead.
$ python sigint.py
24^C
I got a SIGINT, but I am not stopping
26^C
I got a SIGINT, but I am not stopping
30^\[1]    39913 quit       python sigint.py

Additional Signals

  • SIGINT and SIGQUIT: Terminal related.
  • SIGTERM: Generic signal for graceful exit.
  • Use kill -TERM <PID> to send SIGTERM.

Pausing and Backgrounding Processes

  • SIGSTOP pauses a process.
  • Ctrl-Z sends SIGTSTP, a terminal version of SIGSTOP.
  • Continue with fg (foreground) or bg (background).
  • Check jobs with jobs command.

Example Session

$ sleep 1000
^Z
[1]  + 18653 suspended  sleep 1000
$ nohup sleep 2000 &
...
$ jobs
...
$ kill -STOP %1
...
$ kill -SIGHUP %1
...

Signals to Remember


Terminal Multiplexers


Introduction

  • Want multiple terminal sessions? Use terminal multiplexers.
  • Examples: tmux and screen.
  • Run side-by-side sessions, detach and reattach later.

Using tmux

  • Keybindings form: <C-b> x.
  • Sessions, Windows, and Panes.
  • Detailed commands and hierarchy explained.

Aliases


Introduction

  • Shortcuts for long commands or common flags.
  • Structure: alias alias_name="command_to_alias arg1 arg2"

Alias Examples

alias ll="ls -lh"
alias gs="git status"
alias v="vim"
alias sl=ls
alias mv="mv -i"
...

Aliases Persistence

  • Aliases do not persist by default.
  • Add to startup files like .bashrc or .zshrc.

Dotfiles


Introduction

  • Plain-text configuration files.
  • Examples: .vimrc, .bashrc.
  • Shell, git, vim, ssh, and tmux are configured using dotfiles.

Organizing Dotfiles

  • Keep in a separate folder.
  • Use version control.
  • Symlink them using a script.

Benefits of Organizing Dotfiles

  • Easy installation on new machines.
  • Portability across systems.
  • Synchronization between machines.

Further Reading

  • Detailed resources for shell startup scripts, tmux, and screen.
  • Explore and customize your toolset!

Portability

A common pain with dotfiles is the configurations might not work across machines. Especially if they have different operating systems or shells.


Sometimes configurations should only apply to a specific machine. There are tricks to make this easier:

  1. Use if-statements for machine-specific customizations.
  2. Use includes for machine-specific settings.
  3. Share configurations across programs.

if [[ "$(uname)" == "Linux" ]]; then {do_something}; fi
if [[ "$SHELL" == "zsh" ]]; then {do_something}; fi
if [[ "$(hostname)" == "myServer" ]]; then {do_something}; fi

In a ~/.gitconfig:

[include]
    path = ~/.gitconfig_local

And ~/.gitconfig_local can have machine-specific settings.


For sharing configurations, such as aliases:

if [ -f ~/.aliases ]; then
    source ~/.aliases
fi

A small break…


Remote Machines

Remote servers are becoming more common in a programmer’s workflow. SSH is the tool to know.

To SSH into a server:

ssh [email protected]

SSH can also run commands directly:

ssh foobar@server ls

SSH Keys

Key-based authentication uses public-key cryptography. The private key (~/.ssh/id_rsa or ~/.ssh/id_ed25519) is your password.


Key Generation

Use ssh-keygen to generate a key pair:

ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id_ed25519

Choose a passphrase for security.


Key Based Authentication

SSH checks .ssh/authorized_keys. To copy a public key:

cat .ssh/id_ed25519.pub | ssh foobar@remote 'cat >> ~/.ssh/authorized_keys'

Or use ssh-copy-id:

ssh-copy-id -i .ssh/id_ed25519 foobar@remote

Copying Files Over SSH

  • Use ssh+tee for simple copies.
  • Use scp for bulk copying.
  • Use rsync for efficient copying.

Port Forwarding

Link local ports to remote ones. Two types:

  1. Local Port Forwarding
  2. Remote Port Forwarding

Local Port Forwarding Local Port Forwarding


Remote Port Forwarding Remote Port Forwarding


Example of local port forwarding:

ssh -L 9999:localhost:8888 foobar@remote_server

Navigate to localhost:9999 on your local machine.


SSH Configuration

Instead of using shell aliases:

alias my_server="ssh -i ~/.id_ed25519 --port 2222 -L 9999:localhost:8888 foobar@remote_server"

Use ~/.ssh/config:

Host vm
    User foobar
    HostName 172.16.174.141
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    LocalForward 9999 localhost:8888

Miscellaneous

Consider Mosh for roaming connections and sshfs to mount remote folders.

Shells & Frameworks

While bash is popular, there are alternatives like zsh with enhanced features:

  • Smarter globbing
  • Spelling correction
  • Better tab completion

Frameworks improve shells:


Terminal Emulators

Choosing a terminal emulator is vital. Consider:

  • Font
  • Color Scheme
  • Shortcuts
  • Tabs/Panes
  • Scrollback

🆕 Warp. For Windows users: the new Terminal