web-dev-qa-db-ja.com

kshで-iオプション(ファイルからSQLを読み取る)を指定してsqlcmdを実行した後のファイル記述子やI / Oストリームの予期しない動作により、無限ループが発生します

kshスクリプトで無限ループを作成せずにsqlcmd-i input_fileオプションとともに使用する方法はありますか?

  • コードは$fileから行を読み取り、それを1行ずつ解析して、データを抽出し、他のものを処理します。
  • ファイル記述子のリダイレクトを使用して、「stdinから$fileを読み取ります」。

無限ループコード:

exec 3<&0
exec 0<"${file}"
while read -r line || [[ -n ${line} ]]
do
    echo "${line}"
    sqlcmd -S svr -U usr -P pwd -i input_file >/dev/null 2>&1
done
exec 0<&3
exec 3<&-
echo "Script completed successfully!"

出力:

line 1 ...
line 1 ...
...
line 1 ...^C

回避策-i input_fileオプションの代わりにヒアドキュメントを使用):

exec 3<&0
exec 0<"${file}"
while read -r line || [[ -n ${line} ]]
do
    echo "${line}"
    sqlcmd -S svr -U usr -P pwd <<-EOF
        -- SOME SQL CODE HERE
    EOF
    # here document lines are indented with tabs, not whitespaces.
done
exec 0<&3
exec 3<&-
echo "Script completed successfully!"

出力:

line 1 ...
line 2 ...
line 3 ...
Script completed successfully!

この問題の回避策がある場合でも、その動作の理由と、-i input_fileオプションを禁止せずにsqlcmdツールを使用する方法を知りたいと思います。

注:

  • Microsoft ODBC SQLServer用のドライバー11。
  • Red Hat Enterprise Linux 6.7(KornShell)。
2
CamelCamelius

@meuhがコメントで述べたように、sqlcmdstdinを読んでいたので、</dev/nullを追加すると問題が修正されました。問題は、whileループがstdin(以前はファイルexec 0<"${file}"からリダイレクトされた)とsqlcmd内にあるwhileを反復処理していたことでした。 stdinから読み取ろうとしました。解決策は、stdinではなく/dev/nullからsqlcmdを読み取るようにすることでした。

修正

exec 3<&0
exec 0<"${file}"
while read -r line || [[ -n ${line} ]]
do
    echo "${line}"
    sqlcmd -S svr -U usr -P pwd -i input_file </dev/null
done
exec 0<&3
exec 3<&-
echo "Script completed successfully!"
0
CamelCamelius