Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何从程序中收集日志和输出,并将它们传递到函数的参数中_Bash_Shell_Sh_Embedded Linux - Fatal编程技术网

Bash 如何从程序中收集日志和输出,并将它们传递到函数的参数中

Bash 如何从程序中收集日志和输出,并将它们传递到函数的参数中,bash,shell,sh,embedded-linux,Bash,Shell,Sh,Embedded Linux,我有一个shell脚本,它有一个记录语句的函数 #!/bin/sh Log() { echo $1 >> /some/logfile } Log "Test logging works" 这太棒了 接下来,我有一个记录语句的程序,如果我想将其中的日志添加到一个文件中,我可以这样做 SomeProgram >> SomeFile.txt 这也非常有效 但是,如果我想将日志从SomeProgram传递到我的函数Log,同时从同一shell脚本调用SomePro

我有一个shell脚本,它有一个记录语句的函数

#!/bin/sh

Log() {
    echo $1 >> /some/logfile
}

Log "Test logging works"
这太棒了

接下来,我有一个记录语句的程序,如果我想将其中的日志添加到一个文件中,我可以这样做

SomeProgram >> SomeFile.txt
这也非常有效

但是,如果我想将日志从
SomeProgram
传递到我的函数
Log
,同时从同一shell脚本调用
SomeProgram
,该怎么办。可能吗?以下是我尝试过的一些不起作用的技巧

Log "SomeProgram >> SomeFile.txt"
Log(SomeProgram >> SomeFile.txt)
问题
那么,我如何从程序中收集日志并将其传递到函数的参数中呢

环境:

Linux

使用
tee
分割输出

Log "$(SomeProgram | tee -a SomeFile.txt)"
说明:

SomeProgram | tee
将stdio输出从
SomeProgram
传递到
tee
命令

tee-a SomeFile.txt
将输出到stdio,同时
-a
添加到
SomeFile.txt


Log“$(……”
将捕获括号内命令的stdio,并将结果作为参数传递给
Log
函数。

您可以编写一个函数来处理标准输入和任何参数:

Log(){
#如果STDIN(0)不是终端,则迭代任何标准输入行
[!-t0]&&while read line;do echo“$line”>>/some/logfile;done
#迭代提供的任何参数
对于arg;执行echo“$arg”>>/some/logfile;完成
}
如果您有一个连续输出文本行的程序,您可以通过管道将该程序的标准输出传输到函数的标准输入,手动输入参数,或者两者兼而有之

SomeProgram|Log
记录“第一行”“第二行”
SomeProgram |记录“附加第1行”和“附加第2行”

查看
manbash
/^*复合命令
,了解可用于函数的所有语法类型。

如果是一次性的,我会编写一个循环

SomeProgram | while IFS= read -r line; do
    Log "$line"
done
如果你打算经常这样做,你可以在
Log
中添加第二个模式,它从stdin而不是它的参数中读取

Log() {
    case $1 in
        --stdin)
            while IFS= read -r line; do Log -- "$line"; done
            return;;

        --)
            shift;;
    esac

    echo "$*" >> /some/logfile
done


不要!这样做会导致
Log()
在任何时候以非交互方式调用脚本时使用stdin。好的脚本在自动化和用于管道时表现良好;他们不坚持键盘输入。

记录“$(./SomeProgram)”
这不起作用吗?SomeProgram的输出应该传递给Log。我不确定SomeFile.txt与您尝试执行的操作有什么关系?命令替换将等待SomeProgram完成,然后再传递一个值,这对于正在进行的日志记录是不可取的;执行,否则它将跳过不以换行符结尾的行。惯用的方法是当IFS=read-r line时使用
,这样就不会忽略前导和尾随空格。@vintnes我更新了问题描述,将其称为“函数”而不是“方法”。检查stdin是否为tty是一个坏主意。现在,如果用户在管道中运行脚本,它将把所有输入都作为日志消息接收,它将使尝试读取stdin的任何其他命令都无法使用。例如,如果脚本说
Log“询问用户名”;read-p'user:'user
,如果stdin不是tty,
Log
调用将使用
read
的输入。用户可能正试图用
echo“bob”|./script
自动回答提示。
SomeProgram | Log --stdin