Skip to content

Terminal Logs in Linux: Record a Terminal Session with script and Log Every Command

Updated 6 min read

Updated: 9 October 2026 · Applies to: Ubuntu 26.04 (util-linux 2.41.3, bash 5.3, tested), Debian 13, Ubuntu 24.04, AlmaLinux 9 and 10 (script versions checked); sudo I/O logging tested on AlmaLinux 10 and Ubuntu 26.04

Linux does not save what appears in your terminal. Bash only keeps the commands you type, in ~/.bash_history, and not their output. To create a terminal log with both commands and output, start a recording with the script command:

script ~/terminal.log

Everything you type and see is written to ~/terminal.log until you type exit or press Ctrl+D. Below are the useful options, how to record every session automatically, how to log commands with timestamps, and where to find system logs if that is what you are after.

Record a terminal session with script

script is part of util-linux and is already installed on Debian and Ubuntu (package bsdutils). On minimal AlmaLinux, Rocky Linux or Fedora installs, add it with sudo dnf install util-linux.

  1. Start the recording: script session.log. You see Script started, output log file is 'session.log'.
  2. Work as usual.
  3. Type exit to stop. The file now holds the whole session between a start and an end line:
    Script started on 2026-10-09 15:39:39+00:00 [<not executed on terminal>]
    echo hello from the session
    hello from the session
    ...
    Script done on 2026-10-09 15:39:40+00:00 [COMMAND_EXIT_CODE="0"]
    In a real terminal the first line also records TERM, TTY, COLUMNS and LINES.

Options you will use most (from script --help, util-linux 2.41):

  • -a: append to the log instead of overwriting it.
  • -q: quiet, no start and done messages on screen (they are still written to the file).
  • -f: flush after each write, so you can follow the log live with tail -f.
  • -c "command": record one command instead of an interactive shell.
  • -T file (--log-timing): save timing data so the session can be replayed.
  • -o size: stop when the log reaches a size limit.

Log the output of a single command

$ script -q -c "free -m" free.log
$ cat free.log
Script started on 2026-10-09 15:39:39+00:00 [COMMAND="free -m" <not executed on terminal>]
               total        used        free      shared  buff/cache   available
Mem:            3818         675        2041          73        1489        3143
Swap:           1199           6        1193

Script done on 2026-10-09 15:39:39+00:00 [COMMAND_EXIT_CODE="0"]

Run it again with -a and the second run is added below the first.

Replay a session like a video

Record with a timing file, then play it back at the original speed with scriptreplay:

script -q --log-timing demo.tm -c "echo step 1; sleep 2; echo step 2" demo.log
scriptreplay --log-timing demo.tm demo.log

The replay printed step 1, waited two seconds and printed step 2. Add -d 4 (divisor) to replay four times faster, or -m 1 to wait at most one second between updates. Use timing files for programs that redraw the screen, such as top or htop: the log file alone is hard to read for those.

Record every terminal session automatically

Add this to the end of ~/.bashrc:

# Record interactive terminal sessions to ~/logs
if [ -z "$SCRIPT_LOGGING" ] && [ -t 0 ] && [[ $- == *i* ]]; then
  export SCRIPT_LOGGING=1
  mkdir -p ~/logs
  exec script -q -f -a ~/logs/terminal-$(date +%F).log
fi

The SCRIPT_LOGGING variable stops the new shell inside script from starting another recording (without it you get an endless loop), and the [ -t 0 ] and $- checks skip sessions without a terminal, such as scp or scripts. Each day gets its own file. When you type exit, the recording and the terminal close together.

The log also contains terminal control codes (colours, window titles). Read it with less -R, or strip the codes:

sed -e 's/\x1b\][^\x07]*\x07//g' -e 's/\x1b\[[0-9;?]*[A-Za-z]//g' -e 's/\r//g' ~/logs/terminal-$(date +%F).log

which gave clean lines like root@vps:~# echo inside the recording followed by its output.

Command history with date and time

The history command shows your previous commands. Ubuntu's default ~/.bashrc keeps 1,000 commands in memory and 2,000 in the file (HISTSIZE and HISTFILESIZE); AlmaLinux sets HISTSIZE=1000 in /etc/profile. To add timestamps, put this line in ~/.bashrc:

export HISTTIMEFORMAT="%F %T "
$ history 3
    2  2026-10-09 15:40:24 cd /etc
    3  2026-10-09 15:40:24 ls hostname
    4  2026-10-09 15:40:24 history 3

More in set date and time for each command in bash history and change the number of commands stored in bash history.

Log every command to a daily file

To keep your own log of each command with date, user and folder, add this to ~/.bashrc:

# Log every command with date, user and folder
mkdir -p ~/logs
log_cmd() {
  local num cmd
  read -r num cmd <<< "$(HISTTIMEFORMAT= history 1)"
  if [ -z "${__last_logged+x}" ]; then __last_logged=$num; return; fi
  [ "$num" = "$__last_logged" ] && return
  __last_logged=$num
  printf '%s %s %s %s\n' "$(date '+%F %T')" "$USER" "$PWD" "$cmd" >> ~/logs/commands-$(date +%F).log
}
PROMPT_COMMAND="log_cmd${PROMPT_COMMAND:+; $PROMPT_COMMAND}"

Bash runs PROMPT_COMMAND before showing each prompt. The function skips empty Enter presses and keeps any PROMPT_COMMAND your distribution already set. Result:

2026-10-09 15:41:26 root /etc cd /etc
2026-10-09 15:41:26 root /etc ls hostname
2026-10-09 15:41:26 root /etc echo done

The folder is the one you are in after the command ran. A command that starts with a space was not logged, because Ubuntu's default HISTCONTROL (ignoreboth for new users, ignoredups:ignorespace for root) keeps it out of the history. To send commands to the system log instead, see log all bash history commands to syslog.

Audit what admins do with sudo

Users can edit or delete their own logs, so for auditing a server use sudo's I/O logging, which records the full input and output of commands run through sudo. Add a file with sudo visudo -f /etc/sudoers.d/iolog containing:

Defaults log_output

Sessions are saved under /var/log/sudo-io. List and replay them with sudoreplay:

$ sudo sudoreplay -l
Oct  9 16:01:44 2026 : root : HOST=vps ; CWD=/ ; USER=nobody ; TSID=000001 ; COMMAND=/bin/echo hello-from-sudo
$ sudo sudoreplay 000001

This worked on AlmaLinux 10 (sudo 1.9.17p2). Ubuntu 26.04 uses sudo-rs by default, which rejected the setting (unknown setting: 'log_output'). There, switch to the classic sudo with sudo update-alternatives --set sudo /usr/bin/sudo.ws and use sudoreplay.ws to replay.

Looking for system logs instead?

If you searched for terminal logs to read the server's own logs from the terminal, use journalctl on systemd systems (options from the journalctl manual):

  • journalctl -e: jump to the newest entries.
  • journalctl -f: follow new entries live (Ctrl+C to stop).
  • journalctl -u ssh (Debian, Ubuntu) or journalctl -u sshd (AlmaLinux, Rocky): one service.
  • journalctl -b (this boot), --since "1 hour ago" and -p err (errors and worse) narrow it down.

Classic text logs live in /var/log; follow one with sudo tail -f /var/log/FILE.

Related articles

Official documentation: script(1), journalctl(1) and Bash reference manual.

Related services

KVM VPS hosting

NVMe SSD and full root access, with Free Basic Managed Support.

Unmanaged dedicated servers

full root access and free IPMI KVM, with Free Basic Managed Support.

Linux server management

hardening, patching, monitoring and automation for Ubuntu, Debian, RHEL and AlmaLinux.

Was this answer helpful?

Still stuck? Open a ticket