I am skeptical about the redirection operation of below example - linux

I was successful in redirecting the error message to a text file in the below process:
$ ls + 2>err.txt
$ cat err.txt
ls: cannot access +: No such file or directory
But when I try to attempt the same process with echo command it shows different output and unable to redirect the error message to a text file.
$ echo )hey 2>err.txt
bash: syntax error near unexpected token `)'

In your first example, it is the ls command that produces the error message that is written to err.txt.
In your second command, you are expecting the following to happen:
The line is successfully parsed
bash opens err.txt for the standard error of echo
echo tries to output )hey
echo encounters an error
The error message is written to err.txt.
However, bash never makes it past the first line, so none of 2 through 5 ever happens. Instead, the shell immediately stops processing the line and prints the error message to its own standard error.

Related

No Error from Script for Non-Existent File

I have a shell script that reads a text file and uses its content. So far so good. But now I'm trying to make the script exit if the file is not found. The script looks like this
#!/bin/bash
function errorcatcher() {
errorcode=$?
echo "ERROR CODE : ${errorcode}"
exit ${errorcode}
}
trap errorcatcher ERR
MYFILE=$1
IFS='|'
while read line; do
echo ${line}
done < ${MYFILE}
echo "Execution complete"
And I run the script as
sh myscript.sh /home/mydir/ABC.txt
and it works fine. But if I try this
sh myscript.sh /home/mydir/nonexisting.file
I get
myscript.sh: line 17: /home/mydir/nonexisting.file: No such file or directory
Execution complete
Function errorcatcher does not get invoked and instead of exiting with an error code, the execution continues and I get the line Execution complete even though the file in question doesn't exist. My guess is no error is generated here, so I added this line before reading the text file
ls ${MYFILE}
The errorcatcher gets invoked this time. But if I try
sh myscript.sh /home/mydir/ABC.tx
Instead of existing file ABC.txt, I pass its incomplete name ABC.tx and again, the errorcatcher function is not invoked and the script completes successfully (Execution complete gets echoed).
Could someone help me with this? I'm curious as to why errorcatcher doesn't get invoked
for a non existing file without ls
for incomplete file name (ABC.tx) with ls
Function errorcatcher does not get invoked …
Indeed, with an error in the redirection of a loop like
while read line; do
…
done < ${MYFILE}
the ERR trap is not invoked. You have discovered an undocumented exception in the implementation of the trap command, or, if you prefer, a bug.
You can evade that by adding an additional test of the redirection before the while, e. g. the line
<$MYFILE
on its own will invoke the error trap.

Why does read throw an error in bash but works fine?

This bash script writes an array to a file and then reads the file back into a different array. (This is useful for array-based communication between scripts.) However, a strange, non-reported error is trapped by the IFS line (line 12). Why?
#!/bin/bash
# eso-error-ic
trap 'echo Error trapped, with code $?, on line ${LINENO}' ERR
# write data to a file
arr=(0 abc) && printf "%s\n" "${arr[#]}" > eso.out
# read data from the file into an array
# throws an error!!
IFS=$'\n' read -d '' -a new_arr < eso.out
# but it worked...
echo ${new_arr[0]}
echo ${new_arr[1]}
Script output:
Error trapped, with code 1, on line 12
0
abc
What's missing is any sort of message displayed when the error is produced. All you get is the message from the trap but no message about what the error is.
In other words, the IFS/read line produces an error, which is trapped, but no error message is displayed and the line properly reads the file into an array variable. It works, reports no error, but an "error" is trapped.
If you comment out the trap line OR switch to the command/eval/cat approach to reading a file into an array (as suggested here), no error is trapped. Here is what the command/eval/cat line would look like for this script (to replace line 12):
IFS=$'\n' GLOBIGNORE='*' command eval 'new_arr=($(cat eso.out))'
The error comes from not receiving the delimiter that read was expecting. I get the same with
read -d x variable <<<"hello"
If I change the input to "hellox" the error disappears.
As mentioned by #Aserre, a detailed analys is at our Unix & Linux sister site and as pointed out by #CharlesDuffy a common workaround is
read variable || [[ $variable ]]
which is used even without -d to cope with files which might lack the final terminating newline.

How to run a script using diff for a command?

I'm writing a script to test a program and I'm getting caught at this portion
if (("$x"==22)); then
echo "Checking for whether wrong input file is detected."
if diff ${arr[$x]} <(./compare ); then
echo Output is as expected.
else
echo Output is not as expected. Check for errors.
fi
else
if diff -q ${arr[$x]} <(./compare $i); then
echo Output is as expected.
else
echo Output is not as expected. Check for errors.
fi
fi
So what it's doing is testing my program against known output. However, for the case where I use ./compare without an argument, I want to receive an error message from my program specifying that the argument is missing. The test file it's using, "22" let's call it result22.txt, has the exact same output my program would give from just running ./compare (no arguments). However, when I run it using the script, it says that result22.txt differs from just running ./compare. I'm pretty sure I"m running the script wrong, any ideas?
Additionaly information, i is a known input test file that's from an array, x is an incremental variable to count which loop we're on. So arr[$x] is just accessing the nth file from the known output files.
Compare is my own compare program to run.

closing stdout and stderr (1>&- 2>&-) modifies exit status?

Does ls -l /path/to/dir/*.extension 1>&- 2>&-
really giving exit status as 2 even if files with .extension exist or am I making some mistake?
What I know by doing 1>&- 2>&- I am closing stdout and stderr for command, and it should do nothing with exit status of command!
But as one expects following always works pretty fine:
ls -l /path/to/dir/*.extension &>/dev/null
exit status is 0 as expected.
Just looking for an explanation for this behaviour.
#UNDERSTANDING
On basis of answer given by Simon Richter:
If we do something like
jordan-a#hosties:exp$ echo "Life" 1>&-
-bash: echo: write error: Bad file descriptor
it's throwing error since echo couldn't write to stdout and
if we do
jordan-a#hosties:exp$ echo "Life" 1>&- 2>&-
We would not even get to know the error, till the time we check $?
You are closing the file descriptors, so the program will get an error trying to write to them, and it communicates that error to you.
If you redirect the output to /dev/null, the write succeeds, and ls doesn't know that the output got discarded.

KornShell (ksh) redirection

I have a script which redirects std out/std err as below:
SCRIPTS=/test/scripts
LOG=/test/log
echo $SCRIPTS
echo $LOG
$SCRIPTS/dmm_algo_ofac_daily_sched.ksh >> $LOG/test12.log 2>&1
This script is not able to expand $SCRIPTS and $LOG
If I replace it as below:
/test/scripts/daily_sched.ksh >> /test/log/test12.log 2>&1
It complains as below:
: bad file unit numberd/test.ksh: line 33: 1
Also I am not able to invoke the script from the directory where it is saved. If I do
./test.ksh it gives me error saying file not found. I am able to execute it via ksh /test/sched/test.ksh though.
Can someone help me with these. Thanks in advance.
I'm almost certain that the problem is because of DOS/Windows line endings
The error message you are getting is overwriting itself because of a carriage return. You can fix your file using dos2unix.
Add magic #!/bin/ksh to the first line to invoke directly without naming the interpreter on the command line.
I'll conjecture wildly that your root cause(s) has (have) nothing to do with redirection.
Is the script you've exhibited /test/sched/test.ksh or /test/scripts/test.ksh? Are you certain?

Resources