Option One: Making ssh
provide a TTY
Pass -tt
to ssh to force it to provide a TTY, and pass TERM
through explicitly if you don't trust ssh to be configured to do so implicitly:
#!/bin/bash
# ^^^^- the below printf usage is not available in baseline POSIX sh
printf -v term_q '%q' "$TERM"
ssh -t root@"$node_name" "TERM=$term_q bash -s" < ./script.sh
Of course, this only makes sense if your ssh
is run from a terminal. If it's run from a cron job, then you need something different.
Option Two: Making Do Without One
The operation you're running is one that only makes sense in the context of a terminal. With no terminal, there doesn't exist a terminal width for tput
to look up; and with no terminal type set via the TERM
environment variable, there's no control sequence available for it to use.
Consider setting a default for noninteractive use:
# if we have no TERM, and no preexisting COLUMNS, set our own
[[ $TERM || $COLUMNS ]] || COLUMNS=80
...or writing your code to handle the case itself:
# skip this command altogether if we have no TERM or COLUMNS
[[ $TERM || $COLUMNS ]] && printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -
(Note that assigning to COLUMNS
is not particularly well-defined behavior; some shells may not allow it; they're well within the POSIX specification to do so, as the shell and system utilities are allowed to make their own use of all-caps variable names; only lower-case names are guaranteed safe for other applications to use).