我想从shell脚本中运行一个程序(当它执行时生成logdata)并将输出写入文本文件。我没有这样做:/
$ prog是已执行的prog - > socat /dev/ttyUSB0,b9600 STDOUT
$ log / $ FILE只是.txt文件的路径
我有一个Perl脚本来执行此操作:
open (S,$prog) ||die "Cannot open $prog ($!)\n";
open (R,">>","$log") ||die "Cannot open logfile $log!\n";
while (<S>) {
my $date = localtime->strftime('%d.%m.%Y;%H:%M:%S;');
print "$date$_";
}
我尝试在像这样的shell脚本中执行此操作
#!/bin/sh
FILE=/var/log/mylogfile.log
SOCAT=/usr/bin/socat
DEV=/dev/ttyUSB0
BAUD=,b9600
PROG=$SOCAT $DEV$BAUD STDOUT
exec 3<&0
exec 0<$PROG
while read -r line
do
DATE=`date +%d.%m.%Y;%H:%M:%S;`
echo $DATE$line >> $FILE
done
exec 0<&3
根本不起作用......
如何使用shell脚本读取该prog的输出并将其输入到我的文本文件中?我做错了什么(如果我没有做错什么)?
最终代码:
#!/bin/sh
FILE=/var/log/mylogfile.log
SOCAT=/usr/bin/socat
DEV=/dev/ttyUSB0
BAUD=,b9600
CMD="$SOCAT $DEV$BAUD STDOUT"
$CMD |
while read -r line
do
echo "$(date +'%d.%m.%Y;%H:%M:%S;')$line" >> $FILE
done
答案 0 :(得分:1)
要从流程中读取,请使用流程替换
exec 0< <( $PROG )
/bin/sh
不支持,因此请改用/bin/bash
。
要为变量,引号或反斜杠空格指定多个单词:
PROG="$SOCAT $DEV$BAUD STDOUT"
分号在shell中是特殊的,引用它或反斜杠:
DATE=$(date '+%d.%m.%Y;%H:%M:%S;')
此外,不需要任何执行人员:
while ...
...
done < <( $PROG )
您甚至可以在> $FILE
之后添加done
,而不是将每行分别添加到文件中。
答案 1 :(得分:0)
您没有显示错误消息 - 这会有所帮助。
但你的问题可能就在这一行:
DATE=`date +%d.%m.%Y;%H:%M:%S;`
其中分号标记命令的结尾,并且可能没有执行任何有用的命令%H
等。
您需要围绕date
格式参数的引号,并且我会为此作业使用单引号:
DATE=$(date +'%d.%m.%Y;%H:%M:%S;')
甚至用以下代码替换循环体中的两行:
echo "$(date +'%d.%m.%Y;%H:%M:%S;')$line" >> $FILE
双引号可以防止各种问题。
假设您修复了许多其他问题,例如设置变量FILE
和prog
。另外,我可能会使用:
exec > $FILE
最初删除输出文件,然后所有后续标准输出将转到该文件,因此echo
行变为:
echo "$(date +'%d.%m.%Y;%H:%M:%S;')$line"
这个问题最初缺少很多关键信息。它最终得到了更新,包括完整的代码。
我最初确定的问题仍然是一个问题,但您没有遇到它,因为输入重定向无法正常工作。如果您希望输入来自进程,请使用管道,或者可能process substitution。但请注意,您有#!/bin/sh
作为shebang行,而/bin/sh
将无法识别进程替换;要么改变shebang,要么使用管道符号。请注意,如果循环设置了在循环完成后需要访问的变量,则进程替换具有优势。
$SOCAT $DEV$BAUD STDOUT |
while read -r line
do
…
done
或
while read -r line
do
…
done < <($SOCAT $DEV$BAUD STDOUT)
请注意,您的代码包含以下行:
PROG=$SOCAT $DEV$BAUD STDOUT
这将运行$DEV$BAUD
标识的命令,其参数为STDOUT
,环境变量PROG
设置为$SOCAT
的值。那不是你想要的。
您可以使用数组:
PROG=($SOCAT $DEV$BAUD STDOUT)
然后运行:
"${PROG[@]}"
在管道中:
"${PROG[@]}" |
while read -r line
do
…
done
或使用流程替换:
while read -r line
do
…
done < <("${PROG[@]}")
请注意,除非在最终exec 0<&3
之后有代码,否则在涉及文件描述符3的重定向中没有特别的优点。当你完成它时,你也应该关闭3:
exec 0<&3 3>&-
“最终”代码包括以下行:
CMD="$SOCAT $DEV$BAUD STDOUT"
$CMD |
while read -r line
这可以正常工作,因为命令的参数中没有空格。这是一种常见的情况,但要注意参数和文件路径中的空格。