wch*_*gin 10 bash io-redirection shell-script
我目前使用以下设置来重定向多个命令的输出:
echo "Some normal commands"
(
echo "Error: something happened"
echo "Warning: this incident will be logged"
) >> logfile
echo "More normal commands"
Run Code Online (Sandbox Code Playgroud)
这非常有用,它也适用于管道。
这是最好的方法吗?有没有我应该考虑的替代方案?
gle*_*man 17
另一种方法是使用大括号而不是圆括号。此更改在当前shell 中执行命令,而不是在子 shell 中
echo "Some normal commands"
{
echo "Error: something happened"
echo "Warning: this incident will be logged"
} >> logfile
echo "More normal commands"
Run Code Online (Sandbox Code Playgroud)
参考:https : //www.gnu.org/software/bash/manual/bashref.html#Command-Grouping
当您修改组内的变量时,这尤其重要:
$ x=5; ( x=10; echo inside: $x; ); echo outside: $x
inside: 10
outside: 5
$ x=5; { x=10; echo inside: $x; }; echo outside: $x
inside: 10
outside: 10
Run Code Online (Sandbox Code Playgroud)
格伦的回答很好——( ... )和{ ... }是很重要的。
我经常用于错误输出的一种策略是tee命令。你可以这样做:
echo "Normal output"
{
printf "[%s] %s\n" "$(date '+%Y-%m-%d %T')" "Warning text"
printf "[%s] %s\n" "$(date '+%Y-%m-%d %T')" "This event is logged."
} | tee -a $logfile >&2
echo "More normal output"
Run Code Online (Sandbox Code Playgroud)
该tee命令会将输出发送到两个地方;-a选项“附加”输出到命名文件,并且该命令还将输入传递到标准输出。的>&2在该行重定向的端部tee的标准输出到stderr,其可以被不同地处理(即,在定时任务)。
我经常在 shell 脚本中使用的另一个技巧是根据脚本是在终端上运行还是提供了-v选项来更改调试或详细输出的行为。例如:
#!/bin/sh
# Set defaults
if [ -t 0 ]; then
Verbose=true; vflag="-v"
else
Verbose=false; vflag=""
fi
Debug=false; AskYN=true; Doit=true
# Detect options (altering defaults)
while getopts vdqbn opt; do
case "$opt" in
v) Verbose=true; vflag="-v" ;; # Verbose mode
d) Debug=true; Verbose=true; vflag="-v" ;; # Very Verbose
q) Verbose=false; vflag="" ;; # quiet mode (non-verbose)
b) AskYN=false ;; # batch mode
n) Doit=false ;; # test mode
*) usage; exit 1 ;;
esac
done
# Shift our options for further processing
shift $(($OPTIND - 1))
$Verbose && echo "INFO: Verbose output is turned on." >&2
$Debug && echo "INFO: In fact, expect to be overrun." >&2
# Do your thing here
if $AskYN; then
read -p "Continue? " choice
case "$choice" in
Y|y) $Doit && somecommand ;;
*) echo "Done." ;;
esac
fi
Run Code Online (Sandbox Code Playgroud)
脚本可以从顶部这样的通用内容开始,详细和调试输出散布在整个脚本中。这只是一种方法——有很多方法,不同的人都有自己的方法来处理这些事情,特别是如果他们已经存在一段时间了。:)
另一种选择是使用“处理程序”来处理您的输出——一种可以做更智能事情的外壳函数。例如:
#!/bin/bash
logme() {
case "${1^^}" in
[IN]*) level=notice ;;
W*) level=warning ;;
A*) level=alert ;;
E*) level=emerg ;;
*) level=notice ;;
esac
if [[ "$#" -eq 1 ]]; then
# Strip off unnecessary prefixes like "INFO:"
string="${1#+([A-Z])?(:) }"
else
shift
string="$@"
fi
logger -p "${facility}.${level}" -t "$(hostname -s)" "$string"
}
echo "Normal output"
logme INFO "Here we go..."
somecommand | logme
echo "Additional normal output"
Run Code Online (Sandbox Code Playgroud)
(请注意,这${var^^}是仅限 bash 的。)
这将创建一个 shell 函数,它可以使用您系统的syslog函数(使用logger命令) to send things to system logs. Thelogme()` 函数可以与生成单行日志数据的选项一起使用,也可以与在 stdin 上处理的多行输入一起使用。如果它可以使用它似乎很有吸引力。
请注意,这是一个示例,除非您理解它并知道它完全符合您的需要,否则可能不应逐字复制。更好的主意是采用此处的概念并在您自己的脚本中自己实现它们。
| 归档时间: |
|
| 查看次数: |
11013 次 |
| 最近记录: |