Redirect _sudo_ 's PID, stderr and stdout to file - bash

How can _user_ redirect PID as well as stdout and stderr of sudo (and not of the sub-shell it spawns) to file ?
I.e. the sudo passwd request ([sudo] password for _user_: _) and any error normally sent to the current shell's stdout and stderr by sudo should be redirected to any appropriate file /path/foobar, in the spirit of:
{sudo-process} &> >(tee /path/foobar > /dev/null) or
{sudo-process} 2>&1 | tee /path/foobar &>/dev/null)
as far as stdout and stderr are concerned. In my use case, PID is also needed to make unattended killing of the sudo process possible from an external script with appropriate privis.
By "current shell", I mean the shell in which the sudo process lives.
The farthest I got to is a possible askpass program (see option -A in man 8 sudo) and the possibility to use plugins which may or may not be relevant. I have no experience at all with that. Can you help ?
Note: I am NOT looking at redirecting output from a shell spawned by sudo to file. As in:
$ sudo cmd &> /path/foobar or $ sudo sh -c 'cmd &> /path/foobar'
depending on whether /path/foobar is a file with appropriate write permission, i.e. accessible to cmd's redirection of stdoutand stderr. This is not the issue.
EDIT:
#JohnKugelman suggests running sudo -n which causes sudo to emit an error message to stderr and to die, in case a passwd is needed. That takes care of:
- redirecting stdout, since there is none anymore.
- the need to store sudo's PID, since the process dies on its own.
The main issue remains: how to redirect sudo's stderr to file ?

To redirect sudo's stderr to file:
sudo -n cmd -- &> /path/of/the/file

Related

How to pipe stderr to notify-send?

I run programs using keybindings, which themselves could call dmenu and do things in the background. I would love to pipe stderr to notify-send and get a notification if something failed.
These programs are not called from a terminal emulator, mostly sxhkd coupled with an xdg-open alternative jaro.
Take this example, for instance:
$ ls /root
"/root": Permission denied (os error 13)
$ ls /root 2> /dev/null
$
If I had an sxhkd entry
super + Return
ls /root
How can I have it output stderr to a notification?
notify-send will not work with piping
However, you can try:
sudo pip install notify-pipe
Which accepts piping
See here: https://github.com/ron7/notify-pipe
And you can pipe stderr to stdout and send it to notify-pipe
command 2>&1|notify-pipe
Create a script notify-pipe:
#!/usr/bin/env sh
read notification
notify-send "Command Failed" "$notification" "$#"
And pipe stderr to stdout:
$ ls /root 2>&1| notify-pipe
Possible enhancement: bash get command that was used before pipe symbol to get the command in the notification summary.
Thanks for the help, Ron.

Run Shell scripts without having messages [duplicate]

I want to make my Bash scripts more elegant for the end user. How do I hide the output when Bash is executing commands?
For example, when Bash executes
yum install nano
The following will show up to the user who executed the Bash:
Loaded plugins: fastestmirror
base | 3.7 kB 00:00
base/primary_db | 4.4 MB 00:03
extras | 3.4 kB 00:00
extras/primary_db | 18 kB 00:00
updates | 3.4 kB 00:00
updates/primary_db | 3.8 MB 00:02
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package nano.x86_64 0:2.0.9-7.el6 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
nano x86_64 2.0.9-7.el6 base 436 k
Transaction Summary
================================================================================
Install 1 Package(s)
Total download size: 436 k
Installed size: 1.5 M
Downloading Packages:
nano-2.0.9-7.el6.x86_64.rpm | 436 kB 00:00
warning: rpmts_HdrFromFdno: Header V3 RSA/SHA256 Signature, key ID c105b9de: NOKEY
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
Importing GPG key 0xC105B9DE:
Userid : CentOS-6 Key (CentOS 6 Official Signing Key) <centos-6-key#centos.org>
Package: centos-release-6-4.el6.centos.10.x86_64 (#anaconda-CentOS-201303020151.x86_64/6.4)
From : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : nano-2.0.9-7.el6.x86_64 1/1
Verifying : nano-2.0.9-7.el6.x86_64 1/1
Installed:
nano.x86_64 0:2.0.9-7.el6
Complete!
Now I want to hide this from the user and instead show:
Installing nano ......
How can I accomplish this task? I will definitely help to make the script more user friendly. In case an error occurs then it should be shown to the user.
I would like to know how to show same message while a set of commands are being executed.
Use this.
{
/your/first/command
/your/second/command
} &> /dev/null
Explanation
To eliminate output from commands, you have two options:
Close the output descriptor file, which keeps it from accepting any more input. That looks like this:
your_command "Is anybody listening?" >&-
Usually, output goes either to file descriptor 1 (stdout) or 2 (stderr). If you close a file descriptor, you'll have to do so for every numbered descriptor, as &> (below) is a special BASH syntax incompatible with >&-:
/your/first/command >&- 2>&-
Be careful to note the order: >&- closes stdout, which is what you want to do; &>- redirects stdout and stderr to a file named - (hyphen), which is not what what you want to do. It'll look the same at first, but the latter creates a stray file in your working directory. It's easy to remember: >&2 redirects stdout to descriptor 2 (stderr), >&3 redirects stdout to descriptor 3, and >&- redirects stdout to a dead end (i.e. it closes stdout).
Also beware that some commands may not handle a closed file descriptor particularly well ("write error: Bad file descriptor"), which is why the better solution may be to...
Redirect output to /dev/null, which accepts all output and does nothing with it. It looks like this:
your_command "Hello?" > /dev/null
For output redirection to a file, you can direct both stdout and stderr to the same place very concisely, but only in bash:
/your/first/command &> /dev/null
Finally, to do the same for a number of commands at once, surround the whole thing in curly braces. Bash treats this as a group of commands, aggregating the output file descriptors so you can redirect all at once. If you're familiar instead with subshells using ( command1; command2; ) syntax, you'll find the braces behave almost exactly the same way, except that unless you involve them in a pipe the braces will not create a subshell and thus will allow you to set variables inside.
{
/your/first/command
/your/second/command
} &> /dev/null
See the bash manual on redirections for more details, options, and syntax.
You can redirect stdout to /dev/null.
yum install nano > /dev/null
Or you can redirect both stdout and stderr,
yum install nano &> /dev/null.
But if the program has a quiet option, that's even better.
A process normally has two outputs to screen: stdout (standard out), and stderr (standard error).
Normally informational messages go to sdout, and errors and alerts go to stderr.
You can turn off stdout for a command by doing
MyCommand >/dev/null
and turn off stderr by doing:
MyCommand 2>/dev/null
If you want both off, you can do:
MyCommand >/dev/null 2>&1
The 2>&1 says send stderr to the same place as stdout.
You can redirect the output to /dev/null. For more info regarding /dev/null read this link.
You can hide the output of a comand in the following ways :
echo -n "Installing nano ......"; yum install nano > /dev/null; echo " done.";
Redirect the standard output to /dev/null, but not the standard error. This will show the errors occurring during the installation, for example if yum cannot find a package.
echo -n "Installing nano ......"; yum install nano &> /dev/null; echo " done.";
While this code will not show anything in the terminal since both standard error and standard output are redirected and thus nullified to /dev/null.
>/dev/null 2>&1 will mute both stdout and stderr
yum install nano >/dev/null 2>&1
You should not use bash in this case to get rid of the output. Yum does have an option -q which suppresses the output.
You'll most certainly also want to use -y
echo "Installing nano..."
yum -y -q install nano
To see all the options for yum, use man yum.
you can also do it by assigning its output to a variable, this is particularly useful when you don't have /dev/null.
Yes, I came across a situation when I can't use /dev/null.
The solution I found was to assign the output to a variable which I will never use there after:
hide_output=$([[ -d /proc ]] && [[ mountpoint -q /proc ]] && umount -l /proc)
This:
command > /dev/null
Or this: (to suppress errors as well)
command > /dev/null 2>&1
Similar to lots of other answers but they didn't work for me with 2> being in front of dev/null.
.SILENT:
Type " .SILENT: " in the beginning of your script without colons.

How to suppress stdout and stderr in bash

I was trying to make a little script when I realized that the output redirection &> doesn't work inside a script. If I write in the terminal
dpkg -s firefox &> /dev/null
or
dpkg -s firefox 2>&1 /dev/null
I get no output, but if I insert it in a script it will display the output. The strange thing is that if I write inside the script
dpkg -s firefox 1> /dev/null
or
dpkg -s firefox 2> /dev/null
the output of the command is suppressed. How can I suppress both stderr and stdout?
&> is a bash extension: &>filename is equivalent to the POSIX standard >filename 2>&1.
Make sure the script begins with #!/bin/bash, so it's able to use bash extensions. #!/bin/sh runs a different shell (or it may be a link to bash, but when it sees that it's run with this name it switches to a more POSIX-compatible mode).
You almost got it right with 2>&1 >/dev/null, but the order is important. Redirections are executed from left to right, so your version copies the old stdout to stderr, then redirects stdout to /dev/null. The correct, portable way to redirect both stderr and stdout to /dev/null is:
>/dev/null 2>&1
Make file descriptor 2 (stderr) write to where File descriptor 1 (stdout) is writing
dpkg -s firefox >/dev/null 2>&1
This will suppress both sources.

Can you redirect STDERR for an entire Bash session?

There are lots of questions regarding redirecting stderr and stdout for a single command or script. What I'd like is to redirect any stderr messages from my Bash session to a log file.
I'd like an interactive bash session where all stderr is redirected to a file.
A horrible way to deal with your problem:
exec 3>&2
trap 'exec 2>>/path/to/your_file' DEBUG
PROMPT_COMMAND='exec 2>&3'
exec 3>&2: we first copy fd 2 to a new fd (here fd 3)
trap 'exec 2>/dev/null' DEBUG: Before each command is executed (and if the shell option extdebug is set, which is the default in interactive shells), the DEBUG trap is executed: here we redirect stderr to the file /path/to/your_file (make sure you give an absolute path).
Before each prompt is displayed, Bash executes the string in the PROMPT_COMMAND variable: here we redirect fd2 to fd3 (and fd3 was a copy of fd2 when it pointed to the terminal). This is necessary to print the prompt.
I wouldn't qualify this as a robust or nice method, yet it might do the job for your purpose.
Yes.
exec 2> elsewhere
or redirect the invoking command.
Not an exact answer but this is what I use. It will display STDERR on the screen and log all of STDOUT and STDERR to a log:
eval $1 2>&1 >>~/max.log | tee --append ~/bash.log

How to hide command output in Bash

I want to make my Bash scripts more elegant for the end user. How do I hide the output when Bash is executing commands?
For example, when Bash executes
yum install nano
The following will show up to the user who executed the Bash:
Loaded plugins: fastestmirror
base | 3.7 kB 00:00
base/primary_db | 4.4 MB 00:03
extras | 3.4 kB 00:00
extras/primary_db | 18 kB 00:00
updates | 3.4 kB 00:00
updates/primary_db | 3.8 MB 00:02
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package nano.x86_64 0:2.0.9-7.el6 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
nano x86_64 2.0.9-7.el6 base 436 k
Transaction Summary
================================================================================
Install 1 Package(s)
Total download size: 436 k
Installed size: 1.5 M
Downloading Packages:
nano-2.0.9-7.el6.x86_64.rpm | 436 kB 00:00
warning: rpmts_HdrFromFdno: Header V3 RSA/SHA256 Signature, key ID c105b9de: NOKEY
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
Importing GPG key 0xC105B9DE:
Userid : CentOS-6 Key (CentOS 6 Official Signing Key) <centos-6-key#centos.org>
Package: centos-release-6-4.el6.centos.10.x86_64 (#anaconda-CentOS-201303020151.x86_64/6.4)
From : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : nano-2.0.9-7.el6.x86_64 1/1
Verifying : nano-2.0.9-7.el6.x86_64 1/1
Installed:
nano.x86_64 0:2.0.9-7.el6
Complete!
Now I want to hide this from the user and instead show:
Installing nano ......
How can I accomplish this task? I will definitely help to make the script more user friendly. In case an error occurs then it should be shown to the user.
I would like to know how to show same message while a set of commands are being executed.
Use this.
{
/your/first/command
/your/second/command
} &> /dev/null
Explanation
To eliminate output from commands, you have two options:
Close the output descriptor file, which keeps it from accepting any more input. That looks like this:
your_command "Is anybody listening?" >&-
Usually, output goes either to file descriptor 1 (stdout) or 2 (stderr). If you close a file descriptor, you'll have to do so for every numbered descriptor, as &> (below) is a special BASH syntax incompatible with >&-:
/your/first/command >&- 2>&-
Be careful to note the order: >&- closes stdout, which is what you want to do; &>- redirects stdout and stderr to a file named - (hyphen), which is not what what you want to do. It'll look the same at first, but the latter creates a stray file in your working directory. It's easy to remember: >&2 redirects stdout to descriptor 2 (stderr), >&3 redirects stdout to descriptor 3, and >&- redirects stdout to a dead end (i.e. it closes stdout).
Also beware that some commands may not handle a closed file descriptor particularly well ("write error: Bad file descriptor"), which is why the better solution may be to...
Redirect output to /dev/null, which accepts all output and does nothing with it. It looks like this:
your_command "Hello?" > /dev/null
For output redirection to a file, you can direct both stdout and stderr to the same place very concisely, but only in bash:
/your/first/command &> /dev/null
Finally, to do the same for a number of commands at once, surround the whole thing in curly braces. Bash treats this as a group of commands, aggregating the output file descriptors so you can redirect all at once. If you're familiar instead with subshells using ( command1; command2; ) syntax, you'll find the braces behave almost exactly the same way, except that unless you involve them in a pipe the braces will not create a subshell and thus will allow you to set variables inside.
{
/your/first/command
/your/second/command
} &> /dev/null
See the bash manual on redirections for more details, options, and syntax.
You can redirect stdout to /dev/null.
yum install nano > /dev/null
Or you can redirect both stdout and stderr,
yum install nano &> /dev/null.
But if the program has a quiet option, that's even better.
A process normally has two outputs to screen: stdout (standard out), and stderr (standard error).
Normally informational messages go to sdout, and errors and alerts go to stderr.
You can turn off stdout for a command by doing
MyCommand >/dev/null
and turn off stderr by doing:
MyCommand 2>/dev/null
If you want both off, you can do:
MyCommand >/dev/null 2>&1
The 2>&1 says send stderr to the same place as stdout.
You can redirect the output to /dev/null. For more info regarding /dev/null read this link.
You can hide the output of a comand in the following ways :
echo -n "Installing nano ......"; yum install nano > /dev/null; echo " done.";
Redirect the standard output to /dev/null, but not the standard error. This will show the errors occurring during the installation, for example if yum cannot find a package.
echo -n "Installing nano ......"; yum install nano &> /dev/null; echo " done.";
While this code will not show anything in the terminal since both standard error and standard output are redirected and thus nullified to /dev/null.
>/dev/null 2>&1 will mute both stdout and stderr
yum install nano >/dev/null 2>&1
You should not use bash in this case to get rid of the output. Yum does have an option -q which suppresses the output.
You'll most certainly also want to use -y
echo "Installing nano..."
yum -y -q install nano
To see all the options for yum, use man yum.
you can also do it by assigning its output to a variable, this is particularly useful when you don't have /dev/null.
Yes, I came across a situation when I can't use /dev/null.
The solution I found was to assign the output to a variable which I will never use there after:
hide_output=$([[ -d /proc ]] && [[ mountpoint -q /proc ]] && umount -l /proc)
This:
command > /dev/null
Or this: (to suppress errors as well)
command > /dev/null 2>&1
Similar to lots of other answers but they didn't work for me with 2> being in front of dev/null.
.SILENT:
Type " .SILENT: " in the beginning of your script without colons.

Resources