我有一个bash脚本,简而言之,通过其他命令生成一个文件(工作正常),然后在脚本中我对生成的文件执行wc命令。我的问题是我在wc命令中使用命令替换,当我执行脚本时,它立即执行此替换,而不是等待在脚本中先前生成文件。我有什么选择?
该脚本是一个shell程序,用于运行Oracle SQL Loader以将数据加载到Oracle Table中。 SQL Loader命令生成一个拒绝记录的文件,我正在尝试对其进行字数统计。这是我的代码:
#!/bin/sh
# Set variables
program_name="My Program Name"
input_dir="/interface/inbound/hr_datafile"
log_dir="/interface/inbound/log"
bad_dir="/interface/inbound/hr_bad"
archive_dir="/interface/inbound/hr_archive"
input_base="Import_20171213"
input_ext="csv"
control_file="data_loader.ctl"
exit_status=0
d=`date "+%Y%m%d"`
t=`date "+%H%M"`
# Check if data file exists, count records
if [ -f ${input_dir}/${input_base}*.${input_ext} ]; then
data_file_name=`ls -1rt ${input_dir}/${input_base}*.${input_ext} | head -1 | cut -c 32-100`
data_file_base=${data_file_name%.*}
echo "Data file name: " ${data_file_name}
echo "Data file base: " ${data_file_base}
no_of_recs=`expr $(wc -l ${input_dir}/${data_file_name} | cut -c 1-8) - 1`
echo "DEBUG no_of_recs: " ${no_of_recs}
no_of_errs=0
else
echo
echo
echo
echo "----------------------------- ${program_name} ------------------------------------------"
echo "----------------------------------- Error report : ------------------------------------------------"
echo
echo "Please place your Data files in the UNIX directory => "${input_dir}
echo "${program_name} Process exiting ..."
echo
echo "---------------------------------------------------------------------------------------------------"
echo
echo
echo
echo
echo
exit 1
fi
# Run SQL*Loader
echo
echo "==> Loading Data...into MY_TABLE table"
echo
# Create a temporary control file to pass the data file name in
cat $XX_TOP/bin/${control_file} | sed "s/:FILENAME/${data_file_name}/g" > $XX_TOP/bin/${data_file_base}_temp.ctl
# NOTE: The following sqlldr format is used to "hide" the oracle user name and password
sqlldr errors=100000 skip=1 control=$XX_TOP/bin/${data_file_base}_temp.ctl data=${input_dir}/${data_file_name} log=${log_dir}/${data_file_base}.log bad=${bad_dir}/${data_file_base}.bad <<-END_SQLLDR > /dev/null
apps/`cat ${DB_SCRIPTS}/.${ORACLE_SID}apps`
END_SQLLDR
exit_status=$?
echo "DEBUG exit_status " ${exit_status}
# Remove temporary control file
rm -rf $XX_TOP/bin/${data_file_base}_temp.ctl
# Check for Errors
if [ -f ${bad_dir}/${data_file_base}.bad ]; then
echo
echo "----------------------------- ${program_name} ------------------------------------------"
echo "----------------------------------- Error report : ------------------------------------------------"
echo
grep 'Record' ${log_dir}/${data_file_base}.log > ${log_dir}/${data_file_base}.rec
grep 'ORA' ${log_dir}/${data_file_base}.log > ${log_dir}/${data_file_base}.err
paste ${log_dir}/${data_file_base}.rec ${log_dir}/${data_file_base}.err ${bad_dir}/${data_file_base}.bad
echo
echo "<---------------------------------End of Error Report---------------------------------------------->"
echo
# Count error records
no_of_errs=$(wc -l ${bad_dir}/${data_file_base}.bad | cut -c 1-8)
no_of_recs=$(expr ${no_of_recs} - ${no_of_errs})
# Remove temp files
rm ${log_dir}/${data_file_base}.rec
rm ${log_dir}/${data_file_base}.err
rm ${bad_dir}/${data_file_base}.bad
else
echo "Bad File not found at ${bad_dir}/${data_file_base}.bad"
fi
if (( ${no_of_errs} > 0 )); then
echo "Error found in data file..."
exit_status=1
else
# Archive the data file if no errors
mv ${input_dir}/${data_file_name} ${archive_dir}/${data_file_base}_$d"_"$t.${input_ext}
echo "Data file archived to ${archive_dir}"
exit_status=0
fi
echo
echo
echo
echo "----------------------------- ${program_name} ------------------------------------------"
echo
echo "Total records errored out :" ${no_of_errs}
echo "Total records successfully read :" ${no_of_recs}
echo "---------------------------------------------------------------------------------------------------"
echo
# Final Exit Status
if [ ${exit_status} -eq 1 ]; then
echo "==> Exiting process...Status : ${exit_status}"
exit 1
fi
if条件检查中引用的文件是生成的文件,因此我要检查文件是否存在,然后在其上运行wc。我知道它过早地执行了,因为这个wc错误出现在我的脚本输出中之前应该:
Data file name: Import_20171213.csv
Data file base: Import_20171213
DEBUG no_of_recs: 27
==> Loading Data...into MY_TABLE table
wc: 0653-755 Cannot open /interface/inbound/hr_bad/Import_20171213.bad.
Username:
SQL*Loader: Release 10.1.0.5.0 - Production on Thu Dec 21 12:42:39 2017
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Commit point reached - logical record count 27
Program exited with status 2
在代码中,.bad文件上的wc命令在sqlldr部分之后执行,但日志显示在调用sqlldr之前发生的错误。
任何想法都将不胜感激!谢谢!
答案 0 :(得分:2)
你没有看到你期望的所有输出 - 在调用SQL * Loader之后的任何内容都丢失了 - 来自wc
的错误来自错误的地方,而不是{{1提示。但是给出你使用的构造不应该是错误的 - 如果文件不存在,Username;
测试应该阻止该行到达。
问题在于它没有看到heredoc的结束。 heredoc开头之外的所有命令都是作为heredoc处理的一部分执行的,但是不会去任何地方或者显示到终端(正如预期的那样),并且所有被评估的方式都会导致{ {1}}意外运行,即使该文件不存在。你看到了if
的输出。
这一切都发生在SQL * Loader启动之前,所以你之后会看到wc
的提示。
从评论中看来,heredoc-ending stderr
实际上是在您的实际代码中缩进的,这在发布的问题中没有反映出来。当你使用Username:
heredoc形式时,暗示它用空格而不是制表符缩进。这导致不被认为是这里doc的结尾。
来自The Linux Documentation Project:
此处文档最后一行的结束限制字符串必须从第一个字符位置开始。没有领先的空白。限制字符串后跟踪空格同样会导致意外行为。空格可以防止限制字符串被识别。
删除空格,这是该行的第一件事就是修复它。