Linux pipe with several programs requiring user input

I wonder how to create a channel

program 1 | ... | program N 

where several programs request user input. The problem is that | launches programs in parallel and, thus, starts reading from the terminal in parallel.

For such cases, it would be useful to have a pipe | , which starts the program (i + 1) only after the program I produced some output.

Edit:

Example:

 cat /dev/sda | bzip2 | gpg -c | ssh user@host 'cat > backup' 

Here both gpg -c and ssh request a password.

The workaround for this particular example would be to create ssh key pairs, but this is not possible for each system, and I was wondering if there was a common solution. Gpg also allows you to pass a passphrase as a command line argument, but this is not recommended for security reasons.

+6
source share
4 answers

You can use this construct:

 (read a; echo "$a"; cat) > file 

For instance:

 $ (read a; echo "$a"; echo cat is started > /dev/stderr; cat) > file 1 cat is started 2 3 

Here 1 , 2 and 3 were entered from the keyboard; cat is started was echoed.

The contents of file after running the command:

 $ cat file 1 2 3 
+1
source

Now I use:

 #!/bin/bash sudo echo "I am root!" sudo cat /dev/disk0 | bzip2 | gpg -c | (read -n 1 a; (echo -n "$a"; cat) | ssh user@host 'cat > backup') 

The first sudo will not allow the second to ask for the password again. As suggested above, read defers ssh startup. I used -n 1 for read , because I do not want to wait for a new line, and -n for echo to translate a new line.

+1
source

for one, you can give gpg a password with the --passphrase option.

For ssh, the best solution would be a key login. But if you need to do a password, the expect will be good. Here is a good example: Use wait in bash script to provide password for SSH command

Also expect that you have some kind of input - so if you don't want to hardcode your passwords, this could be the way to go.

0
source

I needed something like this several times earlier, when the first command in the pipeline requires a password, and the next command does not automatically support this (for example, as less does).

As in Igor's answer, I find it useful to use reading inside a subshell:

 cmd1 | ( read; cat - | cmd2 ) 
0
source

Source: https://habr.com/ru/post/921998/


All Articles