Redirecionar a saída para less de dentro do script

Redirecionar a saída para less de dentro do script

Posso redirecionar a saída de um script para um arquivo de log de dentro do script com exec:

#!/bin/bash
exec > stdout.log 2>&1
echo hello world

É possível redirecionar a saída em lessvez de um arquivo? tentei

#!/bin/bash
exec > >(less) 2>&1

# output some text
for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done

mas isso falha de uma maneira estranha ... quanto menos prompt fica visível, mas você volta ao terminal.

Eu gostaria de configurar isso no início do script (para que possa ser condicional, dependendo dos argumentos, tty, etc.).

Responder1

Você deve fazer com que seu script espere pelo lessprocesso filho, caso contrário, seu script será encerrado antes dele e, lessde repente, ficará fora do grupo de processos em primeiro plano, não sendo mais capaz de ler comandos do terminal ou restaurar as configurações do terminal.

Além disso, para evitar lessesperar para sempre pelo final de sua entrada, seu script deve fechar o canal para ele.

Juntando tudo isso:

exec > >(less) 2>&1
trap 'exec >&- 2>&-; wait' EXIT
# >&- 2>&- => close stdout and stderr => cause EOF on less' stdin

seq 1 50000
# the rest of your script

Mas isso não é muito bom, não é portável para a maioria dos outros shells e depende do comportamento não documentado (e não confiável) do bash: não waitfuncionará bem se você tiver mais de um exec > >(...)em seu script e também aguardará outro plano de fundo processos iniciados com &.


Uma ideia melhor seria fazer com que seu script chamasse a si mesmo, usando uma variável de ambiente para evitar recursão infinita:

if [ ! "$CALLED_MYSELF" ]; then
    set -o pipefail # supported in bash, but not in all the shells  
    CALLED_MYSELF=1 "$0" "$@" 2>&1 | less
    exit
fi

seq 1 50000
# the rest of your script

Responder2

Tente apenas isto (sem a execlinha):

for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done | less

(atualizar)

Se quiser incluir o script inteiro, você pode envolvê-lo com{ ... }

#!/bin/bash
{
# output some text
for (( i=1; i <= 500; i++)) do echo "hello world $i"; done

# whatever output you want...

} | less

informação relacionada