bash 回顯在命令行本身(不在腳本中)執行的命令行
出於文件目的,我的意思是從我執行的命令重定向到文件 stdout 和 stderr。例如,我會執行(我的命令沒有別名那麼簡單,
ll
但它可能無關緊要):$ ll > out-err.dat 2>&1 $ cat out-err.dat drwxr-xr-x 39 us00001 us00001 4096 jul 31 14:57 ./ drwxr-xr-x 3 root root 4096 feb 2 06:06 ../ -rw------- 1 us00001 us00001 62226 jul 31 11:56 .bash_history ...
同樣出於文件目的,我想將我使用的命令行儲存在同一個輸出文件中。預期的行為和輸出是
$ [NEW COMMAND LINE]? $ cat out-err.dat [NEW COMMAND LINE] <- This first line would contain the command line used drwxr-xr-x 39 us00001 us00001 4096 jul 31 14:57 ./ drwxr-xr-x 3 root root 4096 feb 2 06:06 ../ -rw------- 1 us00001 us00001 62226 jul 31 11:56 .bash_history ...
如何才能做到這一點? 我知道我可以編寫一個 bash 腳本並執行它,因此該命令將單獨記錄。我可以進一步編寫一個腳本來將命令行回顯到文件,然後通過重定向到同一個文件來執行它。我正在尋找一種可能的無腳本解決方案。
編輯:回饋一個不錯的答案。這不適合作為評論。
我用 command 測試過
echo_command ll echo_command.sh ../dir > out-err.dat 2>&1
。Script
echo_command.sh
,其中 Isource
,包含函式的定義。
../dir
是一個不存在的目錄,強制一些輸出到stderr
.方法1:效果很好,除了兩個問題:
- 它不理解別名(
ll
在這種情況下;用ls
它替換時)。- 它不記錄重定向部分。
方法2:效果不好。現在重定向部分也列印出來了,但是命令行列印到螢幕而不是重定向到文件。
編輯:對發布的關於
script
實用程序的評論的回饋。它用途廣泛,使用scriptreplay
.
script
可以單獨呼叫,它會生成一個互動式 shell(它不會保留父 shell 的最近歷史記錄)它也可以稱為
script -c <command> <logfile>
. 最後一種形式與 OP 的目標相對應,但它不會將命令本身儲存到日誌文件中。它產生(至少在基本情況下)與<command> > <logfile> 2>&1
.所以看起來這在這裡沒有用。
你可以使用這樣的函式:
echo_command() { printf '%s\n' "${*}"; "${@}"; }
例子:
$ echo_command echo foo bar baz echo foo bar baz foo bar baz
$ echo_command uname uname Linux
正如蒂姆肯尼迪所說,還有一個非常有用的
script
命令:$ script session.log Script started, file is session.log $ echo foo foo $ echo bar bar $ echo baz baz $ exit exit Script done, file is session.log
$ cat session.log Script started on 2018-07-31 16:30:31-0500 $ echo foo foo $ echo bar bar $ echo baz baz $ exit exit Script done on 2018-07-31 16:30:43-0500
更新
如果您還需要記錄重定向和基本上每個 shell 語法(請注意,我添加了一條小
Command line:
消息以輕鬆辨識正在執行的命令):echo_command() { local arg for arg; do printf 'Command line: %s\n' "${arg}" eval "${arg}" done }
請注意,您應該非常小心使用的引用
eval
:$ echo_command 'echo foo > "file 2"; cat "file 2"' Command line: echo foo > "file 2"; cat "file 2" foo
它還一次接受許多命令,而不僅僅是一個:
$ echo_command 'echo foo' 'echo bar' 'echo baz' Command line: echo foo foo Command line: echo bar bar Command line: echo baz baz