2017-12-21 28 views
1

나는 bash 스크립트를 가지고있다. bash 스크립트는 다른 명령을 통해 파일을 생성한다. (잘 작동한다.) 그리고 나중에 스크립트에서 생성 된 파일에 대해 wc 명령을 수행한다. 내 문제는 내가 wc 명령에 대한 명령 대체를 사용하고 스크립트를 실행할 때 스크립트에서 이전에 생성 된 파일을 기다리는 대신 즉시이 대체를 실행한다는 것입니다. 내 옵션은 무엇입니까?쉘 스크립트에서 명령 대체를 지연시키는 방법은 무엇입니까?

스크립트는 Oracle SQL Loader를 실행하여 Oracle 테이블로 데이터를로드하는 쉘 프로그램입니다. SQL 로더 명령은 거부 된 레코드가있는 파일을 생성하며이 파일에서 단어 수를 계산하려고합니다. 이건 내 코드입니다 :

#!/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 조건 검사에서 참조 파일이 생성 된 파일입니다, 그래서 파일이 존재하는지 확인하고 다음에 화장실을 실행하고 있습니다. 나는 그것이해야 전에 화장실 오류가 내 스크립트 출력에 나타납니다 있기 때문에 조기에 실행하는 것 알고 : 코드에서

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

첫 줄 다음에 &&를 사용할 수 있습니까? – msoliman

+0

[Bash에 TRY CATCH 명령이 있습니까?] (https : // stackoverflow.com/questions/22009364/is-there-a-try-catch-command-in-bash) –

+0

[-f $ {bad_dir}/$ {data_file_base} .bad]와 같은 의미입니다. &&? – odinsride

답변

2

Username; 프롬프트 대신에 이전에 SQL * Loader를 호출 한 후 아무 것도 나타나지 않고 wc의 오류가 잘못된 위치에 표시됩니다. 그러나 사용 된 구성을 제공하는 것은 잘못해서는 안됩니다. 파일이 존재하지 않으면 if 테스트를 통해 해당 행이 도달하지 못하게해야합니다.

문제는 heredoc의 끝이 보이지 않는다는 것입니다. heredoc의 시작을 넘어서는 모든 명령은 heredoc 처리의 일부로 실행되지만 예상대로 어디에도 가지 않거나 터미널에 표시되지 않으며 평가중인 모든 것이 wc을 유발합니다. 파일이 존재하지 않아도 예기치 않게 실행됩니다. 그 결과로 stderr 출력이 표시됩니다.

SQL * Loader가 시작되기 전에이 모든 일이 발생하므로 그 이후부터 Username: 프롬프트가 표시됩니다.

댓글에서 heredoc-ending END_SQLLDR은 실제로 게시 된 질문에 반영되지 않은 실제 코드에 들여 쓰기되어있는 것 같습니다. <<- heredoc 양식을 사용 했으므로 탭이 아닌 공백으로 들여 쓰여 있음을 의미합니다. 그것은 그것이 여기에 문서의 끝으로 인식되지 않는 원인이됩니다. The Linux Documentation Project에서

는 :

닫는 제한 문자열하는 여기에 문서의 마지막 줄에, 첫 번째 문자 위치에서 시작해야합니다. 선행 공백은 없을 수 있습니다. 제한 문자열 뒤의 공백을 뒤따라도 마찬가지로 예기치 않은 동작이 발생합니다. 공백은 제한 문자열이 인식되는 것을 방지합니다.

공백을 제거하면 줄의 첫 번째 것만 수정할 수 있습니다.