9

Both of these commands work: (note the -S in sudo tells sudo to read the password from stdin).

echo 'mypassword' | sudo -S tee -a /etc/test.txt &> /dev/null
echo -e '\nsome\nmore\ntext' | sudo tee -a /etc/test.txt &> /dev/null

Now I would like to combine the two, i.e. achieve everything in just one line. But, of course, something like this doesn't work:

echo -e '\nsome\nmore\ntext' | echo 'mypassword' | sudo -S tee -a /etc/test.txt &> /dev/null

What would work? Thanks:) - Loady

PS: Minor unrelated question: is 1> identical to > ? I believe they are..

Anthony Webber
  • 445
  • 2
  • 5
  • 10
  • Yes, the 1 in 1> is implied. – Q23 Sep 12 '17 at 13:48
  • And if you want to run everything on one line, can't you just command1 && command2? – Q23 Sep 12 '17 at 13:48
  • @Q23 echo 'mypassword' | sudo -S && echo -e '\nsome\nmore\ntext' | tee -a /etc/test.txt &> /dev/null doesn't work.. – Anthony Webber Sep 12 '17 at 14:44
  • This sounds like an extremely bad idea. What are you trying to accomplish? Why not just add a NOPASSWD entry to your sudoers file? – Martin von Wittich Sep 12 '17 at 17:23
  • @Martin I'm trying to direct 'mypassword' to sudo, and \nsome\nmore\ntext to tee – Anthony Webber Sep 12 '17 at 20:16
  • 1
    @AnthonyWebber yes, that I understood, but why? Do you need call sudo from a script or a cronjob or something, so that it has to run non-interactively? Then the NOPASSWD option is probably far safer and less complicated than putting the password into a script and trying to pipe it into sudo. – Martin von Wittich Sep 13 '17 at 15:29

3 Answers3

12

This will do:

{ echo 'mypassword'; echo 'some text'; } | sudo -k -S tee -a /etc/test.txt &>/dev/null

The point is sudo and tee use the same stdin, so both will read from the same source. We should put "mypassword" + "\n" just before anything we want pass to tee.

Explaining the command:

  • The curly braces groups command. We can look at {...} as one command. Whatever is in {...} writes to the pipe.
  • echo 'mypassword' will write "mypassword\n" to the pipe. This is read by sudo later.
  • echo 'some text' write "some text\n" to the pipe. This is what will reach tee at the end.
  • sudo -k -S reads password from its stdin, which is the pipe, until it reaches "\n". so "mypassword\n" will be consumed here. The -k switch is to make sure sudo prompt for a password and ignore user's cached credential if it's used recently.
  • tee reads from stdin and it gets whatever left in it, "some text\n".

PS: About I/O redirection: Yes you are right, 1>filename is identical to >filename. They both redirect stdout to filename. Also 0<filename and <filename are identical, both redirect stdin.

Navid Ht
  • 260
  • 1
    This way the password could be seen by another user that runs ps aux. Is that correct? In this same direction, this oneliner echo "some text" | sudo -k -S <<< $PASSWORD tee /etc/test.txt would work, or does it falls into the same problem of having only one STDIN? – Diego Bandeira Jan 25 '22 at 05:15
  • 1
    @DiegoBandeira I tested your suggestion using here strings. The answer is yes and no! It doesn't work in bash, as I expected, but works in zsh. – Navid Ht Jan 25 '22 at 10:59
2

This is a bit late but I find this to work well:

sudo -k && echo -e "password\ntext" | sudo -S tee file > /dev/null 2>&1

This does not require multiple pipes and is simpler to understand.

> /dev/null 2>&1

This redirects all output including the one asking for password to /dev/null.

1

I couldn't put it in a comment, but note that you can combine the -k option with the already existing sudo command, i.e., instead of using

sudo -k && echo 'some text' | { echo 'mypassword'; cat -; } | sudo -S tee -a /etc/test.txt &>/dev/null

you can directly put the -k in the original sudo. It might even be "safer":

echo 'some text' | { echo 'mypassword'; cat -; } | sudo -k -S tee -a /etc/test.txt &>/dev/null
neze
  • 11