| | {{infobox |
| | | title = Automation & the Dev Environment |
| | | chapter = Linux Handbook, chapter 29 — cron, systemd timers, tmux, git, dotfiles, the lived-in system |
| | | core | A system becomes yours: scheduled jobs, persistent sessions, versioned config |
| | | tools | cron · systemd timers · tmux/screen · git · stow/dotfiles · ssh config |
| | | skills | scheduling · multiplexing · versioning your own setup |
| | | next | The capstone — the philosophy and the map |
| | }} |
| | |
| | **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 |
| | |
| | ```sh |
| | 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 |
| | |
| | ```ini |
| | # /etc/systemd/system/backup.timer |
| | [Timer] |
| | OnCalendar=daily |
| | Persistent=true |
| | [Install] |
| | WantedBy=timers.target |
| | ``` |
| | |
| | ```sh |
| | 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 |
| | |
| | ```sh |
| | 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: 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. `tmux -CC` (iTerm2) integrates; `tmate` shares sessions. |
| | |
| | ## The environment files — the complete startup chain |
| | |
| | ```sh |
| | # /etc/profile → /etc/profile.d/*.sh → FIRST of ~/.bash_profile OR ~/.bash_login OR ~/.profile (login — bash stops at the first found) |
| | # ~/.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. |
| | |
| | ## git — versioning everything, including the system |
| | |
| | ```sh |
| | 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 |
| | |
| | ```sh |
| | # 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 |
| | |
| | ```text |
| | # ┌───── 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 |
| | |
| | ```ini |
| | [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 |
| | |
| | ```sh |
| | 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 |
| | |
| | 1. Write a crontab entry; run it; find its logged output. |
| | 2. A systemd timer for a daily job — compare to the cron form. |
| | 3. `tmux`: start a build, detach, reattach — feel the superpower. |
| | 4. `git init` your `~/scripts`; commit your dotfiles. |
| | 5. Write the `.bashrc` additions 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 | |
| | |
| | ## See also |
| | |
| | - [[Shell Scripting]] · [[Inside a Linux System]] · [[Editors]] · [[Linux]] |
| | |
| | [[Category:Linux]] |
| | [[Category:Handbook]] |
| + | [[Category:Linux Handbook]] |
| | |