Перенаправить вывод в less из скрипта

Перенаправить вывод в less из скрипта

Я могу перенаправить вывод скрипта в файл журнала изнутри скрипта с помощью exec:

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

Можно ли перенаправить вывод lessвместо файла? Я пробовал

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

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

но это странным образом не срабатывает... меньше подсказок видно, но вы возвращаетесь к терминалу.

Я хотел бы установить это в начале скрипта (чтобы он мог быть условным, в зависимости от аргументов, tty и т. д.).

решение1

Ваш скрипт должен дождаться lessдочернего процесса, в противном случае он завершится раньше него и lessвнезапно окажется вне группы процессов переднего плана, не имея возможности считывать команды с терминала или восстанавливать настройки терминала.

Кроме того, чтобы предотвратить lessвечное ожидание окончания ввода, ваш скрипт должен закрыть канал к нему.

Собираем все это вместе:

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

Но это не очень хорошо, непереносимо для большинства других оболочек и полагается на недокументированное (и ненадежное) поведение bash: waitне будет работать нормально, если в вашем скрипте их больше одного exec > >(...), и он также будет ждать другие фоновые процессы, запущенные с помощью &.


Лучшей идеей было бы заставить ваш скрипт вызывать сам себя, используя переменную окружения, чтобы избежать бесконечной рекурсии:

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

решение2

Попробуйте просто это (без строки exec):

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

(обновлять)

Если вы хотите включить весь скрипт, вы можете обернуть его в{ ... }

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

# whatever output you want...

} | less

Связанный контент