Search code examples
shelltput

tput: "No value for $TERM and no -T specified" when command run over ssh


I am running shell script from master node in the cluster on all other nodes as,

ssh root@"$node_name" 'bash -s' < ./script.sh

script.sh contains the following line which is used for formatting which adds horizontal line according to the size of the terminal,

printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -

Which gives error and does not print the horizontal line,

tput: No value for $TERM and no -T specified

But when I run it individually on each node, it does not give an error and prints horizontal line.


Solution

  • 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).