How come when I run the command:
hdfs dfs -test -d /user/me/dirs
I have to type in $? to get the result:
sh: 0: command not found
Is there a way I could just get the result (0 or 1)itself and none of the other text?
Pretty terrible at bash so I might be missing something
In bash, $? gives you the exit code of the previous command. Simply typing $? will cause your shell to attempt to execute that return code as a command (which is not usually what you want). You could instead print the value using echo $?, or save it in a variable using retcode=$?.
Exit codes are not normally printed to your shell. The reason you may not be seeing any other output is because the hdfs command is likely not printing any text to your screen (either through stdout or stderr).
I suspect your best option might be hdfs dfs -test -d /user/me/dirs; echo $?, or some variant using a variable.
Exit codes
Understanding exit codes and how to use them in bash scripts
Related
I have an issue that should not be too hard to solve, I just can't figure what I'm doing wrong.
I need to test if a command is successful or not, and the command needs to be executed from a script. The command is:
curl 127.0.0.1:5000 &> /dev/null
Right now there is no server running, so it should always fail. And it does fail when I execute it from a command line. However when I run it from inside a shell script, it fails but the exit code is 0. What could the cause of that be?
Here is the script:
if curl 127.0.0.1:5000 &> /dev/null
then
echo "sucess"
exit 0
else
echo "failure"
exit 1
fi
And here is the output:
success
curl: (7) Failed to connect to 127.0.0.1 port 5000: Connection refused
However, it does work as expected if I remove the redirection (I'm quite a beginner in shell code, but the redirection shouldn't also redirect the exit code right? So I really don't know what this means)
here is the code without redirections that works as expected (therefore that indicates a failure and has an exit code of 1):
if curl 127.0.0.1:5000
then
echo "sucess"
exit 0
else
echo "failure"
exit 1
fi
Anyone has an idea?
Edit:
I was launching the script with sh script_name.sh in zsh. When I use zsh script_name.sh it now works normally. I still don't fully understand why but at least it works!
"&> /dev/null" is interpreted differently in Bourne shell (sh), The "&" puts the command in background, you can test it with "sleep 100 &>/dev/null". Since it successfully put the command in background, it is a success, and the exit status of the backgrounded command is disregarded.
If you want it to work in Bourne shell (sh), use the traditional syntax ">/dev/null 2>&1", and it will work in newer shells as well, i.e. it is more compatible.
In a system where sh is linked to bash, it will work as is.
I've got tcl script with two ways of execution bash script:
#exec bash ./run.sh
open "|bash ./run.sh r"
The bash script is shown below:
#!/bin/bash
ls
if [ "$?" != "0" ]; then
echo "ERROR: Status failed!" > status
else
echo "Everything is OK!" > status
fi
I'm using tclsh for Windows with bash from git bash. When I use:
exec bash ./run.sh
I've got in status file:
Everything is OK!
otherwise:
open "|bash ./run.sh r"
got:
ERROR: Status failed!
Is there any possibility to correctly detect exit code when opened the tcl pipe?
You don't describe whether you get different results out of the ls part of the script. That matters; the ls command is most certainly capable of changing its behaviour according to the environment in which it is invoked. This matters because Tcl executes subprocesses (on Windows) directly using the CreateProcess() system call, rather than the various wrapped versions that Cygwin and git bash use. Other possibilities are that you're launching the script in a different directory and so on.
However, in general we'd expect a script to behave very similarly when launched via exec or via open |… r as they share a common core of functionality. The only differences are to do with how output and termination are waited for.
If you create a subprocess pipeline, by default you won't get to find out about errors from it until you close the pipeline. exec generates any errors “immediately” because it doesn't return control to you until the subprocess has terminated and all output has been read.
I am trying to run .hql file through a shell script like below
#!/bin/bash
cd /path/
hive -f hive_script.hql
but the script 'hive_script.hql' is failing . I want to exit the shell script successfully even hive_script.hql script fails. Is it possible?
If you don't put an explicit exit in your script, the exit code of your script would be the exit code of the last command it ran - in your case, it is the hive -f ... command.
You can add exit 0 at the end of your script to make sure it always exits with zero.
Related:
Raise error in Bash script
If you want the script to exit with 0 even when hive -f hive_script.hql would fail, you can just or the command with something that won't ever throw an error
hive -f hive_script.hql || :
This means that if the hive command fails, bash should also run the second command. In this case, that command is :, which is basically pass from python, and will always return a 0 status.
I have code for setting the zsh as default shell:
if [ -t 1 ]; then
exec zsh
fi
What exactly does the command if [ -t 1 ] do here?
I have code for setting the zsh as default shell:
No, you haven't. That's not what your code does, though it produces a similar effect.
if [ -t 1 ]; then
exec zsh
fi
What exactly does the command if [ -t 1 ] do here?
The command [ -t 1 ] is executed. If it exits with status 0 (indicating success, which for the [ command means the condition evaluates to true) then the commands in the body of the if statement are executed.
It may be a bit surprising that [ is a command, rather than part of shell syntax, but that's the case. Your if could be rewritten equivalently to use the test command instead:
if test -t 1; then
# ...
The other key thing, then, is the -t 1 part. You can find out about that in the manual for the test or [ command, but to save you the trouble, it is a conditional expression that evaluates whether file descriptor 1 (the shell's standard output) is connected to a terminal. This is similar to, but not exactly the same thing as, evaluating whether the shell is an interactive one.
Overall, the code presented has the effect of replacing the current (presumably bash) shell with zsh if the standard output is connected to a terminal. This is indirect, and a bit tricky; it would probably be better to genuinely set your login shell to /bin/zsh (or wherever it is installed) via the chsh command.
if command; then other_command; fi runs command and then, if that command exits with a return code of 0 ("success"), runs other_command.
The command [...] is designed to take the place of the Boolean expressions that you find in traditional programming languages. It has a number of options for what goes between the brackets and exits with 0=success if those options evaluate to a true value.
The specific subcommand -t tests a file descriptor to see if it is attached to a terminal. The file descriptor 1 is where the script's output is going (aka "standard output" or "stdout" for short). So -t 1 is true and [ -t 1 ] returns success if and only if the output of the script is going to a terminal (instead of into a file or pipe or something).
In that case, the current shell is replaced (via exec) by a copy of zsh. Which will hopefully not run the same script, since zsh works the same way and will make the same decision and go into an infinite loop execing itself.
i am a beginner with bash and im trying to understand someone elses bash script. The script consists of several subsequent invokings of rscripts with certain parameters. All these if statements have roughly the same syntax, as follows:
if Rscript -options > log_file.txt 2>&1
script works, do smth.
else
script failed, leave the ship!
I simply cant get my head around why this if statement does what is does. I know that 2>&1 "combines" stderr and stdout. How does this syntax work exactly?
Thanks for the answers.
The Bash built-in command if doesn't use the output of the program to determine the condition, it uses the return code or exit status of the "command" used as the condition.
Using e.g.
if anycommand; then
...
fi
is equivalent to
anycommand
if [ $? == 0 ]; then
...
fi
The anycommand may contain any kind of options and redirections. If you have a series of piped command, the exit code used is the one of the last foreground command, so in a | b | c the exit code of c is used.
Also note that an exit code of zero is considered to be a success, i.e. it is true when used in a condition. Any exit code that is non-zero is false.
In a C program the exit code is what the main function returns, or the value passed to the exit() function.
In a Bash script or function the exit code is what is passed to the built-in exit or return commands.
The numbers are the file descriptor numbers : 2 is the standard error output (stderr) and 1 is the standard output (stdout), so by writing 2>&1 you are saying : redirect the output from 2 (stderr) to the same as 1 (stdout), and in your command it means to log_file.txt.
In the above case you mentioned. we are trying to execute a script in a if condition.
if Rscript -options > log_file.txt 2>&1
As per above statement,
Rscript is a script and variable "options" stores the argument to run the script. When control executes if condition, first it executes Rscript file with the argument that is stored in options. During the execution of Rscript, all print statements related to Rscript will redirected to "log_file.txt" because of "> log_file.txt". Apart from print statements, error that produced during the execution of the script will also be redirected to text file, because of 2>&1 statement.
2>&1, by this statement we are instructing controller to log all the stderr to stdout, where "log_file.txt" is considered as stdout in this case.
Finally, if Rscript returns true value then control will enter into if condition , If not control will execute else condition.