Bash script type inputs when prompted - linux

EDIT: I'm re-writing this because the first time was a bit unclear.
Let's say I have a program (an executable) such that when I run it, it prompts me to enter an input.
For example, I execute ./myProgram
and the program prompts: Please enter your username:
Here, I would type in my username.
Now, how would I write a bash script so that after I start the above program, I can enter inputs to it?
Something along the lines of this:
#!/bin/bash
path/to/myProgram
# And here I would enter the commands, such as providing my username
Thanks

reading values interactively is rather uncommon in *nix scripts, and is frowned upon by those who want to do exactly what you're trying to do. The standard way of doing this would be changing myProgram to accept arguments. At that point it's trivial to do this.
If you really need to use this pattern you need to use some tool like expect, as pointed out by #EricRenouf.

If myProgram reads from standard input, you can use a here-document:
path/to/myProgram <<\END
username
more input if needed
END

Related

Redirecting input to script running in background

I wrote a script for resizing windows, which require orientation and value in form of fraction, like so:
resize.sh -h 1/2
and it works as expected.
I also added -k flag, which means that script require user input, like so:
resize.sh -k -h
and in the script:
read -rsn 2 fraction
which I parse to get values for numerator and denominator.
This works great from command line, but idea behind this is to bind resize.sh -k -h to some key combination, and pass following two keys as input. But when I run script from keyboard, it run as a background process which is not associated with any tty, so read could not get its input. Is there any way to redirect global input to background process, after running it from keyboard.
What I tried so far:
Redirection to /proc/$$/fd/0, which didn't work.
Redirectiong currently active tty stdin to read, like so:
read -rsn 2 fraction < /dev/pts/0
which actually worked, but problem is that not all windows are terminal, e.g. web browser.
If my question is unclear, please feel free to ask for additional clarifications or details, and thanks in advance :)
You can use a named pipe for the process communication.
I made am example script where the background proces is a function.
#!/bin/bash
pipe_name=/tmp/mypipe$$
mkfifo "${pipe_name}"
resize()
{
read fraction < "${pipe_name}"
echo "Resize window to fraction=${fraction}"
}
resize &
read -p "Enter your fraction: "
echo "${REPLY}" > "${pipe_name}"
rm "${pipe_name}"
thank you both for providing very useful information. The solution is combination of both, actually.
First I modified read command in resize.sh to get input from named pipe, as Walter suggested, than I wrote a new, kinda "wrapper" script, which executes resize.sh in background, and than, since Barmar pointed I need a gui window, it starts very small terminal window running read and passing input to named pipe. Further more, using wmctrl I manage to place small terminal window right where currently active window begins, and hide it below (thanks to openbox per-application properties), so it's technically not visible at all :)
It's really too hacky for my liking, but it was really the only option I could think of at this moment, so until I find the better way, this gets the job done.
Once again, thank you both for directing me toward solution, I really appreciate it, cheers :)

Detect and Enter Input on a prompt in shell script

I'm working on a shell script, which has lot of network calls and installations. When it is executed I need to enter yes/no for each prompt. Which is fine.
But now i have a requirement to run it as cron. In which case i won't be able to give inputs for each of the prompt that comes up.
Is there any way I can automate this or have some mechanism of knowing in script that a prompt has come up?
Use the yes command to answer interactive prompts,
yes Y | ./script.sh
The above syntax constantly puts the string Y to all your prompts. You can pass the string as you need after yes.
You can also use expect tool meant for this, but you need to know the exact prompt message for capturing and responding to it accordingly. If your prompt is simple and just need a simple input to pass yes would be the right tool.
Also you can use bash built-in printf, but you need to add the responses manually depending upon the number of prompts you have to respond to, e.g.
printf 'Y\nY\nY\n' | ./script.sh
to send response as Y for three prompts. As again, to avoid doing this manually, prefer using the yes command.

Validate bash syntax

I'm looking for a way to validate the syntax of a bash script without executing it.
bash -n only seems to validate base bash syntax, what I am missing is:
function name validations
un-initialized parameter validations
Any ideas on how to achieve that?
I am also missing the validation of the number of parameters a function takes,
but that sounds like a very hard thing to do in theory, in bash.
In other words what I'd like to do is pretty much take a bash script and "compile" it like I would compile a c++ program.
bash -n is certainly the fundamental way to do that.
However there is also a site that will do some validation for you:
http://www.shellcheck.net/ --And there is a link on the site to the source code if you want to run it locally.

Shell script - input redirection when prompted by the shell script multiple times

We have a shell script that expects multiple user inputs to be entered when prompted. e.g
At first it may ask for the operation to be performed. When that answer is given, it may ask for username then password etc. We want to automate this task by providing the inputs using file redirection i.e.
script < input.
The input file will have all the answers for different questions that the script may ask. However it is not working and the shell script is reading only the first line of the input file. What do I need to change or use to make this work?
What you can use is the program expect. You create a script for it that tells it when to give what input to some command it executes. This way you can automate exactly the kind of thing you're struggling with.
More info on Google and here:
http://www.linuxjournal.com/article/3065
man page: http://linux.die.net/man/1/expect
You say 'it only reads the first line of input.'
So you have to kill the script?
Is there any output? (error messages especially)?
Are you redirecting STDERR to /dev/null or else where? If so, remove that.
Here is the hightest probability helper ... Modify the top-level script and add set -vx at the 2nd line. Then you'll be able to see what was processed, where it has stopped and possibly formulate theories about why it is not processing data.
Any chance that the input file was created in a Windows environment and the cr\lf pair is messing up the expected input?
I hope this helps.
Thanks all for commenting and answering. I tried except and that did not work. So I am going to mention what worked for us. Here was our workflow - 1. At the linux prompt, type the command, it was connect() in our case. 2. Once that command is given, the script would ask for parameters for the command like port number, server etc. we had to provide that manually 3. Then we again are presented with a shell prompt with another input. In our case, we were able to provide the first command connect() at the prompt using file redirection, but the parameter passing was an issue. The solution we found was provide the parameters inside the parentheses of connect only i.e. our input file for redirection would contain - connect(). This worked for us.

how to perform automated Unix input?

How can you set a string to be used instead of standard input? For example, when running the latex command in Unix it will always find some trivial errors, to skip through all errors you have to enter "r" into the command line (I now know that with latex specifically you can use -interactionmode nonstopmode, but is there a more general solution to do this?)
Is there anyway to specify that this should be done automatically? I tried redirecting standard input to read from a file containing "r\n", but this didn't work.
How can I achieve this?
Not all applications that need input can be satisfied with their stdin redirected.
This is because the app can call the isatty C function (if written in C, or some equivalent call for other languages) to determine if the input come from a tty or not.
In such situation, there is a valuable tool to use, and this is expect.
latex --interaction=MODE
where MODE is one of:
errorstopmode: stop at every error and ask for input
scrollmode: scroll over non-fatal errors, but stop at fatal errors (such as "file not found")
nonstopmode: scroll over non-fatal errors, abort at fatal errors
batchmode: like nonstopmode, but don't show messaes at the terminal
For interactive use, errorstopmode (the default) is fine, for non-interactive use, nonstopmode and batchmode are better.
But beware, there are no trivial errors: all errors must be fixed, and all warnings should be fixed if possible.
Redirecting stdin works without problems here:
/tmp $ tex '\undefined\end' <<< r
This is TeX, Version 3.1415926 (TeX Live 2010)
! Undefined control sequence.
<*> \undefined
\end
? OK, entering \nonstopmode...
(see the transcript file for additional information)
No pages of output.
Transcript written on texput.log.
You've got two plausible answers detailing the way to handle Latex specifically. One comment indicates that you need a more general answer.
Most usually, the tool recommended for the general solution is 'expect'. It arranges for the command to have a pseudo-tty connected for input and output, and the command interacts with the pseudo-tty just as it would your real terminal. You tell 'expect' to send certain strings and expect certain other strings, with conditional code and regular expressions to help you do so.
Expect is built using Tcl/Tk. There are alternative implementations for other languages; Perl has an Expect module, for example.
From the man page:
-interaction mode
Sets the interaction mode. The mode can be either batchmode, nonstopmode, scrollmode, and errorstopmode. The meaning of these modes is the same as that of the corresponding \commands.
Looks like -interaction nonstopmode might help you.

Resources