Sending information to a prompt in a shell - shell

I use a CLI that starts a prompt in my shell. However, I usually end up typing the same commands at the prompt. Is there a way to manually automate the starting of the CLI and then send input in one go?
Here is an example: I type spotify to start my music client.
I see:
Type help to see commands.
> list
These are your playlists
1. ...
2. ...
(some lines omitted) where ">" is a prompt I am typing at. I want my script to type list for me then play and then quit and then start a script which plays my iTunes library. How could I go about doing this?

Expect is what I was looking for. It's a UNIX testing and automation tool for exactly this purpose.

You could implement "macro recording". For example, if you type "startrec", the CLI could save all subsequent commands, e.g. "list", "play" and "quit". The you type "stoprec spotify", which stores the command list under the title "spotify". next time when you type "spotify" your CLI could find it in the macro list, and replay the command sequence.

Related

Automatically background interactive process using job control

I have a command line program that receives interactive input.
I want to have the program backgrounded after it has read the input.
After it has read the input, it execs another program. I want to be able to control that program using shell job control.
I am lazy, so I don't want to type C-Z and bg to achieve that.
I am in control of that program (I wrote it and can change it), and it 'knows' when it should be backgrounded.
I'm sure this is achievable (for example, I guess an expect script could start my program, which could then signal its parent (expect) when it's ready to be backgrounded.
What is the best (simplest, easiest, best-behaving) way to achieve this?
Have you tried the following (Assuming bash)?
# Get necessary input
exec "/usr/bin/bash" ./AnotherScript.sh

Bash - Prepare command in cli without executing it

I'm working on a bash script that lets the user configure a number of settings (like for example the current driver or list of drivers, the current release, the current test suite, the current compiler or list of compilers, etc) and which works with a number of tools (compilers, misra analyzer, test report creator, etc). The script defines some aliases like for example: compile, test, misra, report, etc. When such an alias is run by the user, the script prepares about 1-3 sample commands that can be run with that tool and echoes the sample commands on the screen like for example:
s1 = misra current_driver current_compiler
s2 = misra current_drivers_list current_compiler
s3 = misra current_drivers_list current_compilers_list
The user looks at the samples, chooses the most appropriate, types s1, s2 or s3
and hits Enter. The script adds the selected command in the history, as top command. The user presses 'up arrow' and has the command ready to be edited if needed and executed when everything is ok, at a hit of Enter key.
Now, I want to speed up the process of selecting the command, by getting rid of that 'up arrow key' press. What I would like to accomplish is: when user types s1, s2 or s3 and hits Enter, the corresponding command is added in the command line, without being executed. The thing is that I want to obtain the same behavior like the command would have been typed by the user, meaning the user should still be able to edit it, before launching it by pressing Enter.
Is there any method I can use to implement this behavior ?
Thank you

Is prompt available in Vte?

I have a shell running in a Vte.Terminal widget (could be bash, zsh, or any other interactive shell), I would like to monitor it so as to know when the prompt is available and a new command can be started.
I can't seem to come up with a consistent method.
Here are the ideas I've thought of so far:
Monitor for child process exit.
Could work some of the time, but commands that use only built-ins wouldn't spawn a child. (example: "while true; do; echo test; done;") Also When a command is started in background the prompt would be available before the child exited.
Watch for prompt string in Vte output.
Two problems: 1. A simple prompt string such as "#>" could easily be outputted by some script and give a false positive. 2. Knowing what the prompt string is, is problematic.
Any other ideas or a way to get one of the above working?
What my purpose is.
I'm working on a terminal emulator and would like to change the icon based on whether the prompt is available. Also I am attempting to allow commands to be 'queued' to run when next possible.

Bash: how to duplicate input/output from interactive scripts only in complete lines?

How can I capture the input/ output from a script in realtime (such as with tee), but line-by-line instead of character-by-character? My goal is to capture the input typed into the interactive prompts of a script only after backspaces and auto-completion have finished processing (after the RETURN key is hit).
Specifically, I am trying to create a wrapper script for ssh that creates a timestamped log of commands used on remote servers. The script, which uses tee to redirect the output for filtering, works well, but the redirected output gets jumbled with unsubmitted characters whenever I use the backspace key or the up/down keys to scroll through my remote history. For example: service test stopexitservice test stopart or cd ..logs[1Pls -al.
Perhaps there is a way to capture the terminal's scrollback and redirect that like with tee?
Update: I have found a character-based cleanup solution that does what I want most of the time. However, I am still hoping for an answer to this question (which may well be msw's answer that it is very difficult to do).
In the Unix world there are two primary modes of handling keyboard input. These are known as 'raw' in which characters are passed from the terminal to the reading program one at a time. This is the mode that editors (and such) will use because the editor needs to respond immediately when you press a key.
The other terminal discipline is called 'cooked' which is the line by line behavior that you think of as the bash line by line input where you get to backspace and the command is not executed until you press return. Ssh has to take your input in raw, character-by-character mode because it has no idea what is running on the other side. For example, if you are running an editor on the far side, it can't wait for a return before sending the key-press. So, as some have suggested, grabbing shell history on the far side is the only reasonable way to get a command-by-command record of the bash commands you typed.
I oversimplified for clarity; actually most installations of bash take input in raw mode because they allow editor like command modification. For example, Ctrl-P scrolls up the command history or Ctrl-A goes to the beginning of the line. And bash needs to be able to get those keys the moment they are typed not waiting for a return.
This is another reason that capturing on the local side is obnoxiously difficult: if you capture on the local side, the stream will be filled with Backspaces and all of bash's editing commands. To get a true transcript of what the remote shell actually executed you have to parse the character stream as if you were the remote shell. There also a problem if you run something like
vi /some_file/which_is_on_the_remote/machine
the input stream to the local ssh will be filled with movement commands snippets of text including backspaces and so on and it would be bloody difficult to figure out what is part of a bash command and what is you talking to the editor.
Few things involving computers are impossible; getting clean input from the local side of an ssh invocation is really, really hard.
I question the actual utility of recording the commands that you execute on a local or remote machine. The reason is that there is so much state which is not visible from a command log. As a simple example here's a log of two commands:
17:00$ cp important_file important_file.bak
17:15$ rm important_file
and two days later you are trying to figure out whether important_file.bak should have the contents you intended or not. Given that log you can't answer that simple question. Even if you had the sequence
16:58$ cat important_file
17:00$ cp important_file important_file.bak
17:15$ rm important_file
If you aren't capturing the output, the cat in the log will not tell you anything. Give me almost any command sequence and I can envision a scenario in which it will not give you the information you need to make sense of what was done.
For a very similar purpose I use GNU screen which offer the option to record everything you do in a shell session (INPUT/OUTPUT). The log it creates also comes with undesirable characters but I clean them with perl:
perl -ne 's/\x1b[[()=][;?0-9]*[0-9A-Za-z]?//g;s/\r//g;s/\007//g;print' < screenlog.0
I hope this helps.
Some features of screen:
http://speaking-my-language.blogspot.com/2010/09/top-5-underused-gnu-screen-features.html
Site I found the perl-oneliner:
https://superuser.com/questions/99128/removing-the-escape-characters-from-gnu-screens-screenlog-n

how do I enter the input to ruby program when it is running some other tool

I have a requirement where I need to run the ruby script in WINDOWS and which will have the following command
test.rb
Dir.chdir("C://mtn-2//mtn-2.2//bin//")
system("CadTestNode.bat")
Here am running some tool called mtn tool, once I run this program it will display the following in the output pane
CAD Message Test Node
Select from the following options:
m - Show Menu
c - Create Test Case Connection
a - Execute All Test Cases
t - Terminate All Test Cases
x - Terminate Test Case Connection
s - Set Sequence Number
q - Quit
Enter choice:
After this the script is stucked in between, its asking for the input. My question is, is there any way to provide the input via script itself? Onemore thing, here I need to provide input 2-3 times. Is it possible to automate this kind of scenario as am running some other tool from the ruby script.
Thanks inadvance, waiting for your early reply.
Use pipe (Open3) instead of system and you will be able to read from external program as well as reply to it. Of course, for Windows you will have to install win32-open3 from http://rubyforge.org/projects/win32utils
You can use gets() to get the input, as for the rest (automate) sure, why not. Instead of my_input=gets.chomp do my_input='my predefined actions' and parse it accordingly.

Resources