Configuration Information:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -g -O2 -flto=auto -ffat-lto-objects
-fstack-protector-strong -Wformat -Werror=format-security -Wall
uname output: Linux fairybrains 5.15.0-173-generic #183-Ubuntu SMP Thu
Mar 27 13:22:53 UTC 2025 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu
Bash Version: 5.1
Patch Level: 16
Release Status: release
Description:
The bash(1) manual states that LINES and COLUMNS are "automatically set
... in an interactive shell upon receipt of a SIGWINCH". In practice,
both variables are also updated in non-interactive shells whenever
the shell evaluates a command that queries terminal geometry via
ioctl(TIOCGWINSZ), because checkwinsize is enabled by default since
bash 4.3 and applies regardless of interactive mode when a controlling
TTY is present.
This silently breaks scripts that use LINES or COLUMNS as user variables
(e.g. as array names): the array is converted to a scalar and its
[0] element is overwritten with the current terminal height/width.
The behavior depends on whether the script's stdin is a TTY, making
it irreproducible under ssh-without-tty or under cron, but reliably
reproducible from an interactive login.
Repeat-By:
$ cat > /tmp/demo.sh << ‘EOF’
#!/bin/bash
LINES=()
LINES+=(“hello”)
echo "BEFORE: ${LINES[0]}”
ss -tln >/dev/null 2>&1 # any command that calls ioctl(TIOCGWINSZ)
echo "AFTER: ${LINES[0]}”
EOF
$ bash /tmp/demo.sh # from a terminal
BEFORE: hello
AFTER: 73 # current terminal height
$ ssh user@host 'bash /tmp/demo.sh' # without -tt: no TTY allocated
BEFORE: hello
AFTER: hello # works as documented
Fix:
A documentation patch clarifying that LINES/COLUMNS may be updated in
any shell where checkwinsize is enabled and a TTY is available, not
only interactive shells. Suggested wording for the LINES entry:
LINES Used by the select compound command to determine the column
length for printing selection lists. Set automatically when
the checkwinsize option is enabled (default since bash-4.3)
and the shell receives a SIGWINCH or evaluates a command
that queries terminal geometry, regardless of whether the
shell is interactive. Scripts using LINES or COLUMNS as
ordinary variables (especially as arrays) may have their
contents overwritten unexpectedly.
(analogous wording for COLUMNS)
—
Ilya Tsoy
github.com/ilvits