Search code examples
iokshfile-descriptorio-redirectionsqlcmd

Unexpected behavior of file descriptor and/or I/O streams after running sqlcmd with -i option (read sql from file) in ksh creates infinite loop


Is there a way to use sqlcmd with -i input_file option without creating an infinite loop in my ksh script?

  • The code reads lines from $file and parses it line-by-line to extract data and process other stuff.
  • It uses file descriptors redirection to "read the $file from the stdin".

Infinite loop code:

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!"

Output:

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

Workaround (use here document instead of -i input_file option):

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!"

Output:

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

Even if there's a workaround for the issue I would like to know what's the reason for that behavior and how to use the sqlcmd tool without banning it's -i input_file option.

Notes:

  • Microsoft ODBC Driver 11 for SQL Server.
  • Red Hat Enterprise Linux 6.7 (KornShell).

Solution

  • The issue was that sqlcmd was attempting to read from the stdin so appending </dev/null to the sqlcmd command fixed the problem. It is important to notice that I am redirecting the stdin from a file (exec 0<"${file}").

    Fix:

    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!"
    

    Output:

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