How can I respond to a prompt within a shell script running in background?

43,915

Solution 1

You can echo your answer into standard input of script by using a pipe.

echo "My/Path/not/default"| yourscript.sh

Solution 2

If you can provide all the inputs when the script starts, then do so, by redirecting the program's input. That is, instead of running /path/to/installer, run

{ echo '/the/path/where/to/install';
  echo 'answer to the second prompt';
} | /path/to/installer

or use a here document:

/path/to/installer <<'EOF'
/the/path/where/to/install
answer to the second prompt
EOF

If you want to interact with a program from time to time but use your terminal for other things in between, run the program in a terminal multiplexer such as Screen or tmux. With screen, start a session by running screen, then start the program. To do something else, press Ctrl+A, c to create a second window, then Ctrl+A, n to navigate between the windows. To exit Screen but leave the program running, press Ctrl+A, d (“detach”). To come back to the existing Screen session, run screen -rd (screen with no option would start a new session).

Solution 3

To provide an automatic answer, you could use one of the following:

insaller.sh < an_input_file

or

command-line | installer.sh

There is something to notice if the installer.sh script is using read -p, as in the example below:

read -p "Press ENTER for default path or enter path to install software:" answer

man bash specifies that nothing is printed if the standard input is not a terminal.

If this is your situation, then you could try this odd thing:

( sleep 30 ; printf "/my/own/path\n" ) | insaller.sh

You should adapt the number of seconds (30 in above example) to your situation.

If it happens that read -p is not used inside the install script, then you could give a try to this GNU solution:

 tempdir="$(mktemp -d)"
 mkfifo  "${tempdir}"/input
 touch "${tempdir}"/output.log
 ./installer.sh <"${tempdir}"/input >"${tempdir}"/output.log 2>&1 &
 installerpid=$!
 tail --pid=$installerpid -fn 1 "${tempdir}"/output.log | ( fgrep -q "Press ENTER for default path or enter path to install software:"; printf "/new/path\n" ) >> "${tempdir}"/input &

 # ... do stuff


 # before ending the script, just wait that all background processes stop
 wait
 rm -f "${tempdir}"/input "${tempdir}"/output.log

The idea is to use 2 background command-lines, one for the install script, and one to wait the prompt and provide the answer.

A named pipe (input) and a regular file (output.log) are used for communication.

tail --pid=$installerpid -fn 1 "${tempdir}"/output.log prints lines as there are written in the output.log file. It teminates when the installer script terminates.

( fgrep -q ... ; printf .. ) >> ...input: blocks until the prompt is found, and provides the new path to the install script.

Share:
43,915

Related videos on Youtube

37Scheper
Author by

37Scheper

Updated on September 18, 2022

Comments

  • 37Scheper
    37Scheper over 1 year

    I am scripting the installation of software on HP-UX server. Once the script starts it provides a prompt where I am to enter the install path. I need to pass the path to the script so it can continue to run. There is only 1 place in the script where this need exists.

    The prompt from the script is: Press ENTER for default path or enter path to install software:

    I do not want to use the default path, so I must enter a new path. But this script will run in the background and I need to provide the path. I'm not sure of the exact response in script form.

    • Jay jargot
      Jay jargot almost 8 years
      Give a look to my answer, and test it!
  • 37Scheper
    37Scheper almost 8 years
    So inside the same script, after the command to run the installer... ./INSTALL silent ... I should insert the following line ... echo "my/path/not/default/" | installscript.sh ?