解释
当The Script以下运行没有修改时,它会输出(正确):
二一开始
取消注释exec
下面脚本中的语句后,文件描述符 3 指向标准输出,文件描述符 4 指向标准错误:
exec 3>&1 4>&2
并且所有标准输出和标准错误都会记录到文件中,而不是打印到控制台:
# Two variances seen in the script below
exec 1>"TEST-${mode:1}.log" 2>&1 # Log Name based on subcommand
exec 1>"TEST-bootstrap.log" 2>&1 # Initial "bootstrap" log file
当 exec 语句到位时,脚本应创建三个文件(包含内容):
TEST-bootstrap.log
(成功创建 - 空文件)
TEST-one.log
(创建成功)
一开始
TEST-two.log
(未创建)
二一开始
但相反,它似乎在第一个日志文件之后停止并且从不创建TEST-two.log
. 考虑到它与exec
注释掉的语句一起使用,可能会出现什么问题?
剧本
#!/bin/bash
SELFD=$(cd -P $(dirname ${0}) >/dev/null 2>&1; pwd) # Current scripts directory
SELF=$(basename ${0}) # Current scripts name
SELFX=${SELFD}/${SELF} # The current script exec path
fnOne() { echo "one ${*}"; }
fnTwo() { echo "two ${*}"; }
subcommand() {
# exec 3>&1 4>&2
# exec 1>"TEST-${mode:1}.log" 2>&1
case "${mode}" in
-one) fnOne ${*}; ;;
-two) fnTwo ${*}; ;;
esac
}
bootstrap() {
# exec 3>&1 4>&2
# exec 1>"TEST-bootstrap.log" 2>&1
echo "START" \
| while read line; do ${SELFX} -one ${line}; done \
| while read line; do ${SELFX} -two ${line}; done
exit 0
}
mode=${1}; shift
case "${mode:0:1}" in
-) subcommand ${*} ;;
*) bootstrap ${mode} ${*} ;;
esac
exit 0
这个脚本严格来说是我在另一个更复杂的脚本中遇到的问题的一个孤立示例。我试图使其尽可能简洁,但如果需要,我会对其进行扩展。
我正在努力完成的事情(感兴趣的人的额外阅读)
在上面,为了简单起见,The Script我使用 while 循环而不是gnu-parallel ,并使用简单的函数来回显“一”和“二”,以便于调试并在此处提出问题。
在我的实际脚本中,该程序将具有以下功能:list-archives
、download
、extract
,process
它们将从 URL 获取档案列表,下载它们,提取它们的内容,并分别处理生成的文件。考虑到这些操作需要不同的时间,我计划并行运行它们。我的脚本bootstrap()
函数看起来像这样:
# program ./myscript
list-archives "${1}" \
| parallel myscript -download \
| parallel myscript -extract \
| parallel myscript -process
并会这样称呼:
./myscript "http://www.example.com"
我想要完成的是一种启动程序的方法,该程序可以并行调用它自己的函数并记录它所做的一切。这对于确定上次获取数据的时间、调试任何错误等很有用。
我还希望在使用子命令调用程序时记录日志,例如
# only list achives
>> ./myscript -list-archives "http://www.example.com"
# download this specific archive
>> ./myscript -download "http://www.example.com/archive.zip"
# ...