Automation and Dev
The last layer is the personal one — the point where a working system becomes your system: jobs scheduled, sessions that survive disconnects, a config that versions itself, a development environment shaped to your hands. This chapter covers cron and systemd timers, tmux and screen, git as both tool and practice, and the dotfiles discipline that makes a system reproducible.
cron — the classic scheduler
crontab -e # edit YOUR crontab
crontab -l # list it
# min hour day month weekday command
0 3 * * * /usr/local/bin/backup.sh # 3am daily
*/15 * * * * /usr/local/bin/check.sh # every 15min
0 0 1 * * /usr/local/bin/monthly.sh # the 1st
@daily /path/script.sh # the readable form
@reboot /path/start.sh # at boot
/etc/crontab + /etc/cron.d/ + /etc/cron.daily/hourly/weekly/monthly for system jobs. Cron's output mails to the user — MAILTO="" silences it; redirect to a log instead. The classic gotcha: cron's environment is minimal — scripts need full paths and exported vars.
systemd timers — the modern equivalent
# /etc/systemd/system/backup.timer
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
systemctl enable --now backup.timer
systemctl list-timers # the scheduled world
journalctl -u backup.service # its log
Timers beat cron where logging + dependencies matter; OnCalendar= reads like English; Persistent=true runs missed jobs after downtime — cron can't.
tmux — the complete map
tmux # new session
tmux new -s work # named session
tmux ls # list
tmux attach -t work # reattach — the superpower
tmux new -s x \; send-keys 'cmd' Enter \; detach # scriptable
tmux kill-session -t work # destroy
tmux kill-server # all of them
# inside — Ctrl-b is the prefix:
Ctrl-b d — detach
Ctrl-b c — new window Ctrl-b , — rename it Ctrl-b w — window list
Ctrl-b % — split vertical Ctrl-b " — split horizontal
Ctrl-b arrows — move panes Ctrl-b { } — swap panes
Ctrl-b x — kill pane Ctrl-b z — zoom pane
Ctrl-b [ — scrollback mode — q to exit, /to-search, Space copies
Ctrl-b s — session list Ctrl-b : — command mode
Ctrl-b ? — the key map
:set -g mouse on — the mouse config
Ctrl-b $ — rename session
Sessions survive SSH disconnects — the killer feature. tmux -CC (iTerm2) integrates; tmate shares sessions.
The environment files — the complete startup chain
# /etc/profile → /etc/profile.d/*.sh → ~/.bash_profile → ~/.bash_login → ~/.profile (login)
# ~/.bashrc (interactive non-login) # $BASH_ENV (non-interactive)
# ~/.bash_logout (logout)
# ~/.inputrc — readline: how EVERYTHING reads input — set editing-mode vi
# ~/.profile — POSIX shell's own
# ~/.zshrc — zsh's
# ~/.tmux.conf ~/.vimrc ~/.gitconfig ~/.ssh/config ~/.config/*
~/.inputrc shapes every readline app — set editing-mode vi gives vi keys in bash, psql, python, everywhere readline reads.
tmux — sessions that survive
tmux # new session
tmux new -s work # named
tmux ls # sessions
tmux attach -t work # reattach — the superpower
# inside: Ctrl-b d detach · Ctrl-b c new window · Ctrl-b % split · Ctrl-b " horizontal split
# Ctrl-b [ scrollback · Ctrl-b w window list · Ctrl-b , rename
Detach-and-reattach is the killer feature — ssh in, start a build, Ctrl-b d, disconnect, the build runs on; reconnect tomorrow, tmux attach, everything's there. screen is the classic equivalent; tmux is the modern one.
git — versioning everything, including the system
git init; git add .; git commit -m "first"
git status; git diff; git log --oneline
git checkout -b experiment # branches = safe experiments
git merge experiment
git stash; git stash pop # the clipboard
git clone url; git pull; git push
.gitignore # what NOT to version
Version your own work — scripts, configs, dotfiles, even notes. git init in ~/scripts, a repo for the dotfiles — the config becomes diff-able, recoverable, portable.
Dotfiles — the reproducible setup
# the setup as files
~/.bashrc ~/.bash_profile ~/.vimrc ~/.tmux.conf ~/.gitconfig ~/.ssh/config
# the discipline: version them
mkdir ~/dotfiles; mv ~/.bashrc ~/dotfiles/
ln -s ~/dotfiles/.bashrc ~/.bashrc # symlinked — the stow pattern
gnu stow dotfiles # or the tool
The dotfiles repo is the answer to "I rebuilt my machine" — clone it, symlink it, your environment travels. stow automates the symlinking; bare repos + git --git-dir=~/.dotfiles --work-tree=~ is the no-tool method.
The cron grammar — the five-field contract
# ┌───── minute (0–59)
# │ ┌─── hour (0–23)
# │ │ ┌─── day of month (1–31)
# │ │ │ ┌─── month (1–12)
# │ │ │ │ ┌─── day of week (0–7, 0 and 7 = Sun)
# │ │ │ │ │
* * * * * command
* — every
*/15 — every 15
0 — at 0
1,15 — the 1st and 15th
1-5 — range
0 3 * * * — 3am daily
0 */6 * * * — every 6 hours
0 0 * * 0 — Sunday midnight
0 9 1 * * — 9am on the 1st
@daily @weekly @monthly @yearly @reboot — the readable forms
Cron's environment is minimal — scripts need PATH set, full paths, no tty. MAILTO="" kills the mail; redirect output to a log instead.
The systemd timer grammar
[Timer]
OnCalendar=daily # readable calendar spec
OnCalendar=*-*-* 03:00:00 # 3am daily — the precise form
OnCalendar=Mon *-*-* 09:00:00
OnCalendar=hourly / weekly / daily / monthly / yearly
OnBootSec=15min # 15m after boot
OnUnitActiveSec=1h # 1h after the service last ran
Persistent=true # catch up on missed runs — cron can't
AccuracySec=1min # batch wakeup — power-saving
RandomizedDelaySec=5m # jitter — the thundering-herd fix
systemctl list-timers --all shows the next/elapsed runs; journalctl -u foo.timer the history.
The development environment — the assembled whole
export EDITOR=vim; export PAGER=less # the env that shapes everything
alias ll='ls -lah'; alias ..='cd ..' # the shortcuts
export PATH="$HOME/bin:$PATH" # your own tools first
~/.inputrc # readline — how EVERYTHING reads input
history; Ctrl-R # the working memory
The pieces compound: a tuned .bashrc (aliases, PATH, PS1), .inputrc (readline keys), .vimrc, .tmux.conf, .gitconfig — the environment that feels like yours is these files, versioned.
The automation philosophy
Automate what's repeated: alias, a function, a script, a cron job — the four scales. &&-chains for one-offs; functions for reusable commands; scripts for multi-step; cron/timers for scheduled. The discipline isn't the tool — it's noticing the repetition.
Where it goes wrong
| Symptom | Cause |
|---|---|
| cron job silently does nothing | Minimal env — full paths, or MAILTO ate the error |
| tmux session gone after reboot | Sessions don't persist through reboots — tmux-resurrect or scripts |
| ssh config ignored | ~/.ssh/config needs Host matching exactly |
| Dotfiles broke on a new machine | A host-specific var — conditionals or per-host files |
git committed a secret | .gitignore + pre-commit checks |
| Systemd timer didn't run after downtime | Persistent=true missing |
Exercises
- Write a crontab entry; run it; find its logged output.
- A systemd timer for a daily job — compare to the cron form.
tmux: start a build, detach, reattach — feel the superpower.git inityour~/scripts; commit your dotfiles.- Write the
.bashrcadditions that would make a fresh system yours.
Timeline
| Tool | The layer |
|---|---|
| cron | Scheduled jobs |
| systemd timers | Cron + logging |
| tmux | Persistent sessions |
| git | Versioned work |
| dotfiles | The reproducible self |