I am trying to automate something using shell script.
My question is when there is a system prompt, for e.g. "Do you want to continue (y/n):"
And I need to input y using my shell script, how can it be done ? So at the end when the system prompt displays on the shell then my shell script should be automatically able to enter y.
Thanks in advance.
You can try an expect script
It is used to automate control of interactive applications such as
telnet, ftp, passwd, fsck, rlogin, tip, ssh, and others. Expect uses
pseudo terminals (Unix) or emulates a console (Windows), starts the
target program, and then communicates with it, just as a human would,
via the terminal or console interface.
It is really quite easy using redirection, and there are several ways to do it. This uses a here string. First to generate that system prompt:
more one.sh
read -p "Do you want to continue (y/n): " ans
echo "Answer was $ans"
Now the script to run the program:
bash one.sh <<< 'y'
Output:
Answer was y
Warning! This works by redirecting the process's standard input stream. Some programs, particularly when getting passwords, access the terminal driver at a low level for security reasons.
Related
I'm writing a shell script to set a VNC password using vncpasswd.
The only way to use vncpasswd is in interactive mode (enter password, return, confirm password, return).
How can I respond to the prompts in my shell script so I can set the password automatically? (i.e. non-interactive).
Thanks!
Chris.
If the program is reading from your terminal instead of stdin, you'll find that it ignores any data you send in using file redirection. If that's the case, then you can use a program like expect to automate interactions with the terminal using a pseudy-tty. This is exactly the sort of problem it was designed to solve.
I have a shell script like this :
#!/bin/sh
echo "What's your favorite color ?"
read user_color
echo "You like $user_color"
Whatever the settings I try with Platypus, the prompt is never shown on execution, thus the variable is not defined and never displayed. Is this something possible ?
read requires a controlling terminal (or at least a usable standard input), presumably in your environment no such terminal/input exists and so read cannot read any information (and echo has no standard output to send data to, assuming you don't see that either).
This limitation is in the platypus documentation and a workaround using CocoaDialog is given there as well.
ftp ipaddress
bin
hash
cd path
get filename
quit
i want these line to be executed in a shell script only first line is executing after entering username and password the rest line are not executing and the control is stuck at ftp> prompt
Once your script invokes the program ftp, the shell loses control until the ftp program finishes. So you need to use some new technique. One way is with the program expect, which you can get a hint about here: https://stackoverflow.com/a/12598169/4323 . Another way is to use a more "scriptable" FTP client, such as lftp on Linux, which has specific features to enable the sort of scripted use you're going for.
You need to use a non-interactive FTP client if you want to do this in a script rather than an interactive shell. ncftp is one you could check out.
Or you can use a shell "here" document:
#!/bin/bash
ftp -in <<EOS
user pswd
bin
hash
cd path
get filename
quit
EOS
The here document sends everything via the open program's stdin, just as if you typed it in at the command line. Note that ftp clients can be finicky and each one seems to have it's own set of gotchas, so some experimentation and use of man ftp will likely be required.
Looks like this has come up before on Stackoverflow, you might want to read through
how to ftp multiple file using shell script
IHTH
I am trying to implement a terminal emulator in Java. It is supposed to be able to host both cmd.exe on Windows and bash on Unix-like systems (I would like to support at least Linux and Mac OS X). The problem I have is that both cmd.exe and bash repeat on their standard output whatever I send to their standard input.
For example, in bash, I type "ls", hit enter, at which point the terminal emulator sends the input line to bash's stdin and flushes the stream. The process then outputs the input line again "ls\n" and then the output of the ls command.
This is a problem, because other programs apart from bash and cmd.exe don't do that. If I run, inside either bash, or cmd.exe, the command "python -i", the python interactive shell does not repeat the input in the way bash and cmd.exe does. This means a workaround would have to know what process the actual output came from. I doubt that's what actual terminal emulators do.
Running "bash -i" doesn't change this behaviour. As far as I know, cmd.exe doesn't have distinct "interactive" and "noninteractive" modes.
EDIT: I am creating the host process using the ProcessBuilder class. I am reading the stdout and stderr and writing to the stdin of the process using a technique similar to the stream gobbler. I don't set any environment variables before I start the host process. The exact commands I use to start the processes are bash -i for bash and cmd for cmd.exe. I'll try to post minimal code example as soon as I manage to create one.
On Unix, run stty -echo to disable "local echo" (i.e. the shell repeating everything that you type). This is usually enabled so a user can edit what she types.
In your case, BASH must somehow allocate a pseudo TTY; otherwise, it would not echo every command. set +x would have a similar effect but then, you'd see + ls instead of ls in the output.
With cmd.exe the command #ECHO OFF should achieve the same effect.
Just execute those after the process has been created and it should work.
I'm writing an Expect script and am having trouble dealing with the shell prompt (on Linux). My Expect script spawns rlogin and the remote system is using ksh. The prompt on the remote system contains the current directory followed by " > " (space greater-than space). A script snippet might be:
send "some command here\r"
expect " > "
This works for simple commands, but things start to go wrong when the command I'm sending exceeds the width of the terminal (or more precisely, what ksh thinks is the width of the terminal). In that case, ksh does some weird horizontal scrolling of the interactive command line, which seems to rewrite the prompt and stick an extra " > " in the output. Naturally this causes the Expect script to get confused and out of sync when there appears to be more than one prompt in the output after executing a command (my script contains several send/expect pairs).
I've tried changing PS1 on the remote system to something more distinctive like "prompt> " but a similar problem arises which indicates to me that's not the right way to solve this.
What I'm thinking might help is the ability for the script to tell Expect that "I know I'm properly synchronised with the remote system at this point, so flush the input buffer now." The expect statement has the -notransfer flag which doesn't discard the input buffer even if the pattern does match, so I think I need the opposite of that.
Are there any other useful techniques that I can use to make the remote shell behave more predictably? I understand that Expect goes through a lot of work to make sure that the spawned session appears to be interactive to the remote system, but I'd rather that some of the more annoying interactive features (such as the horizontal scrolling of ksh) be turned off.
If you want to throw away all output Expect has seen so far, try
expect -re $
This is a regexp match on $ which means the end of the input buffer, so it will just skip everything received so far. More details at the Expect man page.
You could try "set -o multiline" or COLUMNS=1000000 (or some other suitably large value).
I have had difficulty with ksh and Expect in the past. My solution was to use something other than
ksh for a login shell.
If you can change the remote login to other than ksh (using the chsh command or editing /etc/passwd) then you might try this with /bin/sh as the shell.
Another alternative is to tell KSH that the terminal is a dumb terminal - disallow it from doing any special processing.
$ export TERM=""
might do the trick.