Suppress output from & in Linux terminal - linux

I've seen answers from multiple posts talking about sending output from a program to /dev/null and also suppressing error output by using 2>&1, but how can I use all of these AND suppress output from sending it to a background process by typing the & symbol?
Example:
feh "image.jpg" & >/dev/null 2>&1
still returns "[#] {PID}" (with the numbers filled in of course). If anyone can help me out that would be greatly appreciated.
I am using Manjaro Linux and my kernel version is 5.11.10-1-MANJARO

Once & is encountered, the first command (feh "image.jpg") is sent to the background, then separately the shell executes >/dev/null 2>&1, which executed alone like this does nothing. You need to set up the output pipes/redirection before sending the process to background:
feh "image.jpg" > /dev/null 2>&1 & echo "Second command"
Note that > /dev/null is the same as 1> /dev/null which means you can do >/dev/null 2>/dev/null or 1>/dev/null 2>/dev/null to get the same effect.
For the job termination output, you can wrap your command in parenthesis like this:
(feh "image.jpg" > /dev/null 2>&1 & echo "Second command" )
As mentioned in the linked post, be aware that this will make you lose control of the process that you send to back with &.

Related

nohup append the executed command at the top of the output file

Let's say that we invoke the nohup in the following way:
nohup foo.py -n 20 2>&1 &
This will write the output to the nohup.out.
How could we achieve to have the whole command nohup foo.py -n 20 2>&1 & sitting at the top of the nohup.out (or any other specified output file) after which the regular output of the executed command will be written to that file?
The reason for this is for purely debugging purpose as there will be thousands of commands like this executed and very often some of them will crash due to various reasons. It's like a basic report kept in a file with the executed command written at the top followed by the output of the executed command.
A straightforward alternative would be something like:
myNohup() {
(
set +m # disable job control
[[ -t 0 ]] && exec </dev/null # redirect stdin away from tty
[[ -t 1 ]] && exec >nohup.out # redirect stdout away from tty
[[ -t 2 ]] && exec 2>&1 # redirect stderr away from tty
set -x # enable trace logging of all commands run
"$#" # run our arguments as a command
) & disown -h "$!" # do not forward any HUP signal to the child process
}
To define a command we can test this with:
waitAndWrite() { sleep 5; echo "finished"; }
...and run:
myNohup waitAndWrite
...will return immediately and, after five seconds, leave the following in nohup.out:
+ waitAndWrite
+ sleep 5
+ echo finished
finished
If you only want to write the exact command run without the side effects of xtrace, replace the set -x with (assuming bash 5.0 or newer) printf '%s\n' "${*#Q}".
For older versions of bash, you might instead consider printf '%q ' "$#"; printf '\n'.
This does differ a little from what the question proposes:
Redirections and other shell directives are not logged by set -x. When you run nohup foo 2>&1 &, the 2>&1 is not passed as an argument to nohup; instead, it's something the shell does before nohup is started. Similarly, the & is not an argument but an instruction to the shell not to wait() for the subprocess to finish before going on to future commands.

nohup redirection command difference

What is the difference between these 2 below lines?
nohup $CATALINA_HOME/bin/startup.sh $CATALINA_HOME 2> /dev/null &
nohup $CATALINA_HOME/bin/startup.sh $CATALINA_HOME > /dev/null &
I've these lines in 2 of my projects having Tomcat server. One of them is having 2> & other one is just with > symbol.
Appreciate youe help!
Note: The line with 2> if ran in CentOS runs fine but the other one gives warning: "nohup: redirecting stderr to stdout"
Thanks!
Both redirect to /dev/null the first one redirects stderr the second one redirects stdout.
More on that: http://www.tldp.org/LDP/abs/html/io-redirection.html, also a few examples always from tldp http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html
Side note: if you want to redirect both stdout and stderr you could do:
nohup $CATALINA_HOME/bin/startup.sh $CATALINA_HOME &> /dev/null &

How do I know if a bash script is running with nohup?

I have a script to process records in some files, it usually takes 1-2 hours. When it's running, it prints a progress of number of records processed.
Now, what I want to do is: when it's running with nohup, I don't want it to print the progress; it should print progress only when it run manually.
My question is how do I know if a bash script is running with nohup?
Suppose the command is nohup myscript.sh &. In the script, how do I get the nohup from command line? I tried to use $0, but it gives myscript.sh.
Checking for file redirections is not robust, since nohup can be (and often is) used in scripts where stdin, stdout and/or stderr are already explicitly redirected.
Aside from these redirections, the only thing nohup does is ignore the SIGHUP signal (thanks to Blrfl for the link.)
So, really what we're asking for is a way to detect if SIGHUP is being ignored. In linux, the signal ignore mask is exposed in /proc/$PID/status, in the least-significant bit of the SigIgn hex string.
Provided we know the pid of the bash script we want to check, we can use egrep. Here I see if the current shell is ignoring SIGHUP (i.e. is "nohuppy"):
$ egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status && echo nohuppy || echo normal
normal
$ nohup bash -c 'egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status && echo nohuppy || echo normal'; cat nohup.out
nohup: ignoring input and appending output to `nohup.out'
nohuppy
You could check if STDOUT is associated with a terminal:
[ -t 1 ]
You can either check if the parent pid is 1:
if [ $PPID -eq 1 ] ; then
echo "Parent pid=1 (runing via nohup)"
else
echo "Parent pid<>1 (NOT running via nohup)"
fi
or if your script ignores the SIGHUP signal (see https://stackoverflow.com/a/35638712/1011025):
if egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status ; then
echo "Ignores SIGHUP (runing via nohup)"
else
echo "Doesn't ignore SIGHUP (NOT running via nohup)"
fi
One way, but not really portable would be to do a readlink on /proc/$$/fd/1 and test if it ends with nohup.out.
Assuming you are on the pts0 terminal (not really relevant, just to be able to show the result):
#!/bin/bash
if [[ $(readlink /proc/$$/fd/1) =~ nohup.out$ ]]; then
echo "Running under hup" >> /dev/pts/0
fi
But the traditional approach to such problems is to test if the output is a terminal:
[ -t 1 ]
Thank you guys. Check STDOUT is a good idea. I just find another way to do it. That is to test tty.
test tty -s check its return code. If it's 0 , then it's running on a terminal; if it's 1 then it's running with nohup.

Need to redirect an output to /dev/null.... works fine in command line but not in shell

I need to write an execute some command in bash file and ignore the inputs.
Example
pvs --noheadings -o pv_name,vg_name,vg_size 2> /dev/null
The above command works great in command line, but when I write the same in shell, it gives me an error
like
Failed to read physical volume "2>"
Failed to read physical volume "/dev/null"
I guess it looks it as an part of the whole command. Can you please give me some suggestions on how to rectify it?
Thanks in advance.
FULLCODE
#------------------------------
main() {
pv_cmd='pvs'
nh='--noheadings'
sp=' '
op='-o'
vgn='vg_name'
pvn='pv_name'
pvz='pv_size'
cm=','
tonull=' 2 > /dev/null '
pipe='|'
#cmd=$pv_cmd$sp$nh$sp$op$sp$vgn$cm$pvn$cm$pvz$sp$pipe$tonull #line A
cmd='pvs --noheadings -o vg_name,pv_name,pv_size 2> /dev/null' #line B
echo -n "Cmd="
echo $cmd
$cmd
}
main
#-----------------------------------------------------
If you look at the Line A & B both the versions are there, although one is commented out.....
You can't include the 2> /dev/null inside the quoted string. Quote removal happens after redirections are processed. You'll have to do
cmd='pvs --noheadings -o vg_name,pv_name,pv_size'
$cmd 2> /dev/null
for redirection to work properly.
The way you did it, 2> and /dev/null will be parsed as arguments. But you want 2> /dev/null to be bash code, not program argument, so
instead of
$cmd
you should
eval $cmd
That is how things work.
Or if the echo thing is for debugging, you can just set -o xtrace before the command and set +o xtrace after it. And do it the normal way instead of stuffing a string.
I think what's going on is that there is some character inside the line that is either not visible to us or the > is a different character than it appears. After all the shell should swallow the redirect before the command gets to see it, but the command sees 2> and /dev/null as [PhysicalVolume [PhysicalVolume...]]. Alternatively the redirection could be passed quoted (so it loses the special meaning to the shell and gets passed on), see chepner's answer.
tonull=' 2 > /dev/null '
is the issue. Exactly as chepner guessed.
eliminate space between 2 and >
pvs --noheadings -o pv_name,vg_name,vg_size 2>/dev/null

How to redirect the output of an application in background to /dev/null

I would like to redirect the output generated from a background application in Linux to /dev/null.
I am using kate text editor and it prints all the debug messages on the terminal which I would like to redirect to /dev/null.
Any idea how to do it ?
Thanks
You use:
yourcommand > /dev/null 2>&1
If it should run in the Background add an &
yourcommand > /dev/null 2>&1 &
>/dev/null 2>&1 means redirect stdout to /dev/null AND stderr to the place where stdout points at that time
If you want stderr to occur on console and only stdout going to /dev/null you can use:
yourcommand 2>&1 > /dev/null
In this case stderr is redirected to stdout (e.g. your console) and afterwards the original stdout is redirected to /dev/null
If the program should not terminate you can use:
nohup yourcommand &
Without any parameter all output lands in nohup.out
These will also redirect both:
yourcommand &> /dev/null
yourcommand >& /dev/null
though the bash manual says the first is preferred.

Resources