Прямой вывод команды из файла, включая исходную команду, и печать в терминале

8

При запуске некоторых тестов мне нужно выполнить ряд команд. Это было бы чрезвычайно полезно для меня и сэкономило бы много времени, если бы был способ сделать все эти вещи:

  • Запустите команду мне нужно запустить
  • Перенаправить весь вывод команды в указанный файл
  • Включить оригинальную команду в указанный файл
  • Вывести вывод из исходной команды в терминал

Люди предложили использовать tee для меня, который отлично печатает на терминале и отправляет в файл, но не включает оригинальную команду. В итоге я хотел бы получить файл, в котором первая строка - это команда, которую я выполнил, а затем под ней выводится команда.

Кто-то предложил это:

echo "ls -l" | xargs -I{} bash -c "echo >> output.file; eval {} >> output.file"

Но это не печатает вывод в терминале и не включает оригинальную команду в файл.

Буду признателен за любые идеи.

shaneoh
источник
2
Почти дубликат askubuntu.com/q/688498/295286 .
Сергей Колодяжный
Я не нашел это в своем поиске - не совсем то же самое, но, вероятно, привело бы меня к ответу.
shaneoh
да, и именно поэтому я сказал почти дубликат. Но, если честно, с моим мнением, вы могли бы взять практически любое решение оттуда и использовать его с помощью трубопровода tee.
Сергей Колодяжный

Ответы:

14

Это teeты ищешь.

ls -l | tee outfile

выводит вывод ls -lв stdout (то есть в терминал) и одновременно сохраняет его в файл outfile. Но : он не записывает имя команды ни в стандартный вывод, ни в файл. Для этого просто echoвведите имя команды перед запуском команды и направьте оба вывода tee:

( echo "ls -l" && ls -l ) | tee outfile

Это громоздко для типа, так почему бы не определить функцию?

both(){ ( echo "$@" && "$@" ) | tee outfile ;}

После этого вы можете просто запустить

both ls -l

чтобы получить желаемый результат. Поместите функцию в свой, ~/.bashrcчтобы она была определена в каждом новом терминале.

Если вы хотите иметь возможность указать выходной файл в качестве первого аргумента, как в

both output ls -l

вместо этого сделайте это:

both(){ ( echo "${@:2}" && "${@:2}" ) | tee "$1" ;}

Если вы не хотите, чтобы выходной файл был перезаписан, а скорее добавляете его, добавьте -aпараметр в tee.

Десерт
источник
9

Вы можете использовать scriptкоманду, которая создаст файл машинописи всего, что напечатано на вашем терминале. Он создает раздвоенные оболочки и будет записывать все, пока эта оболочка не будет закрыта.

$ script my_output
Script started on Tue 28 Nov 2017 09:46:15 AM UTC
$ whoami
ajefferiss
$ exit
Script done on Tue 28 Nov 2017 09:46:27 AM UTC

Тогда, если я cat my_outputполучу такой же вывод:

$ cat my_output
Script started on Tue 28 Nov 2017 09:46:15 AM UTC
$ whoami
ajefferiss
$ exit
exit

Script done on Tue 28 Nov 2017 09:46:27 AM UTC
AJefferiss
источник
6

Вы можете использовать функцию отладки оболочки вместе с tee:

( set -x; command1 args...; command2 args ) 2>&1 | tee output.log
  • ( ... )запускает под-оболочку, которая позволяет вам «собирать» выходные потоки всех команд, выполняемых внутри под-оболочки. Он также содержит эффект setкоманды ниже для этой вложенной оболочки.

  • set -xвключает параметр xоболочки, который печатает все команды, которые оболочка выполняет в стандартном потоке ошибок, перед их выполнением.

  • 2>&1 перенаправляет поток 2 (стандартная ошибка) в поток 1 (стандартный вывод).

  • | перенаправляет стандартный поток вывода левой команды на стандартный поток ввода правой команды.

  • tee FILEкопирует стандартный поток ввода в файл FILEи в стандартный вывод.

Если ваша последовательность команд уже находится в файле сценария, было бы более целесообразно выполнить ее следующим образом:

bash -x /path/to/script args... 2>&1 | tee output.log
Дэвид Фёрстер
источник