0

I am trying to run a shell script within that I will be calling another script and the 2nd script waits for some commands to be provided. I have used echo to pass the commands but it does not work. the 2nd script keeps on waiting for input.

script1:

#!/bin/sh
set -x
sh script2.sh
echo ".open Simulation\n"
set +x

but this does not yield any result. it keeps on waiting.

output:

./script1.sh
+ sh script2
<Nothing appears here>
  • Does script2.sh do something to allow script1 to continue executing? Otherwise you're never getting to the echo statement because the script is waiting for script2.sh to terminate before moving on to the next step – Eric Renouf Sep 6 '16 at 13:26
3

Every process on Linux systems has one input (stdin) and two outputs (stdout, stderr) by default. Terminals take input from the keyboard and send it to stdin of the shell that they run, and take stdout and stderr from the process and print it to the screen.

When you run a command in the shell (in a terminal), it links its own stdin to that of the process, so any keys you type are sent to the command. It also links their stdout and stderr to its own (which the terminal then prints to the screen). The same thing happens when you run a command inside a script, stdin, stdout, and stderr are linked to that of the parent process, these eventually propagate up to the terminal.

Also, commands in scripts are blocking by default. They will only execute the next command once the one they are running has finished.

Given these let's look at your script (simplifying to the two lines of interest):

sh script2.sh
echo ".open Simulation\n"

What this does is it run sh (which run script2.sh) and attaches its stdin to that of the script and blocks waiting for it to end. The second line will not run until the first process has ended.

Now, anything you type into the shell, for example .open Simulation\n will get send to sh which will send it to your script2.sh. Once (if ever) your script2.sh has finished it will exit and your main script will echo .open Simulation\n to the shell and exit.

Now we know what's going on. How can we fix it? Well you can override the default attaching of stdin, stdout and stderr to where ever you want, including files or other processes. To do this the shell has to powerful utilities, input/output redirection and command pipes.

I/O redirections allow you to redirect input/output to any file decipher you wish for example:

echo "contents of a file" > somefile.txt

This will write contents of a file to somefile.txt by redirecting stdout of the echo command to somefile.txt. Input redirection works the same way:

cat < somefile.txt

Will print the contents of the file to the screen by redirecting cats stdin to read from somefile.txt (note that this is a contrived example, most people will just cat somefile.txt which causes cat to read somefile.txt itself rather than getting the shell to do it.)

Next there are command pipes, these allow you to connect stdout of one program to stdin of another. This sounds like what you want, send the output of echo into stdin of your script:

echo ".open Simulation" | sh script2.sh

Now this works well for simple input, but if you have more than a couple of lines there is an easier way; Heredocs. For example to pipe multiple lines into your script you can

sh script2.sh <<EOD
.open Simulation
.do something
.end Simulation
EOD

Which will send the three line (not including the EOD) to your script ready for your script to processes. If you need to do anything more advanced you can use subcommand redirection as well, which will allow you to redirect the output of a subshell into your program, here with a sleep 1 between each line:

sh script2.sh <(
    echo ".open Simulation"
    sleep 1
    echo ".do something"
    sleep 1
    echo ".end Simulation"
)

In this example your script will see .open Simulation straight away, then after a second it will get .do something then after another second .end Simulation before stdin is closed.

2

Try

echo ".open Simulation" | sh script2.sh

Because in your script you just starting script2.sh and it's waiting for input. With the pipe you sending the output of echo to the standard-input of script2.sh

And sorry, you don't need to insert '\n' in the echo, because it's prints a newline character by default. (Thanks thrig)

  • Doesn't echo add a newline by default? – thrig Sep 6 '16 at 14:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.