Can you prompt for user input in a shell script that is running remotely? - linux

Say I have a script that will be run on a remote machine.
While running, the script computes some value.
I want to prompt the user so she can change this value if needed.
Is this possible?
I am running the script like: ssh $usr#$machine 'bash -s' < a.sh "param1" "param2"
In a.sh the read alternateValue function call seems to be ignored.
Or can anyone suggest a different approach?

The read statement reads data from stdin, but you are redirecting stdin in your command line with the < operator, so read isn't going to do anything useful.
What if you were first to copy the script over to the remote host, and then run:
ssh $usr#$machine 'bash /path/to/a.sh param1 param2'
Because there is no redirection happening here, read would work without a problem.

Related

how to execute ssh comand on .sh file?

I trying to create a .sh file that execute things like "pwd" or "ls" command.
My problem its when i execute the .sh file.
Its seems not recognize the tasks
I tried to use echo
Example : echo 'lsApps' or echo "lsApps"
but it prints the name of the task instead execute the comand
for example i want to execute a .ssh file that makes a pwd
VAR_1=pwd
echo $VAR_1
but it prints me pwd instead the current path ...
Any idea?
echo is used to print on the screen (man page reference). If you do echo 'IsApps' it will take it as a string and print it. If you want to execute a command you can just do it by doing IsApps (acutes not quotes, acute is usually below the escape key). This will execute the command and show the output on the screen. If you want to store the output of the command in a variable, you can do
<variable_name>=`IsApps`
This will store the output in the variable. Note that there is no space between variable name and the command. Also, those are not quotes but instead acutes. To print the variable on screen you can use echo by doing echo $<variable_name>
If you don't want to see the output at all. You can do
IsApps > /dev/null
this will execute the command but you will not see any stdout on your screen.
As far as ssh is concerned, do ssh-keygen and then ssh-copy-id user#remote_ip to set ssh keys so that you don't have to enter your password with ssh. Once you have done that, you can use ssh user#remote_ip in your shell script.

Linux shell wrap a program's stdin and stdout using pipes

So, I have this interactive program that is running on an embedded linux ARM platform with no screen and that I cannot modify. To interact with it I have to ssh into the embedded linux distro, and run the program which is some sort of custom command line with builtin commands, and it does not exit, only SIGINT will quit the program.
I'm trying to automate it by letting it run in the background and communicate with it using pipes by sending SSH commands like this ssh user#host echo "command" > stdinpipe. This part works, I've been provided with an example like this in a shell script (I cannot use bash, I only have ash installed on the machine) :
#!/bin/sh
mkfifo somePipe
/proc/<PID>/exe < somePipe 2>&1 &
I can now easily command the program by writing to the pipe like
echo "command" > somePipe
and it outputs everything inside the terminal. The problem is that while it works if I have an SSH session open, it won't if I only send commands one by one as I said earlier (I'm using paramiko in python with the exec_command() method, just in case, but I don't think that is relevant, I could use invoke_session() but I don't want to have to deal with recv())
So I figured out I'd redirect the output of the program to a pipe. That's where problems arise. My first attempt was this one (please ignore the fact that everything is run as root and stored in the root home folder, that's how I got it and I don't have the time to make it cleaner now, plus I'm not the one managing the software) :
cd /root/binary
mkfifo outpipe
mkfifo inpipe
./command_bin &
# find PID automatically
command_pid=$(ps -a | egrep ' * \.\/command_bin *' | grep -v grep | awk '{print $1}')
/proc/${command_pid}/exe < inpipe 2>&1 &
echo "process ./command_bin running on PID ${command_pid}"
That alone works within the terminal itself. Now if I leave the SSH session open and open another terminal and type ssh root#host "echo command > /root/binary/inpipe" the code gets executed, but then it outputs the command I just typed and its result into the other terminal that stayed open. So it is obviously not an option, I have to capture the output somehow.
If I change ./command_bin & for ./command_bin >outpipe & the program never starts, I have no idea why, I know that because $command_pid is empty and I cannot find the process with ps -A
Now if instead I replace /proc/${command_pid}/exe < inpipe 2>&1 & with /proc/${command_pid}/exe < inpipe &>outpipe & the program starts, I can write to inpipe just fine with echo "command" > inpipe when the script finished running, however if I try any of cat < outpipe, tail outpipe it just hangs, and does nothing. I've tried using nohup when starting the command but it doesn't really help. I've also tried using a normal file for redirecting the output instead of a fifo, but with the exact same results.
I've spent the entire day on this thing and I cannot get it to work. Why is this not working ? Also I am probably just using an awful way to do this, is there any other way ? The only thing that's mandatory here is that I have to connect through ssh to the board and the command line utility has to stay open because it is communicating with onboard devices (using I2C, OneWire protocols etc).
To keep it simple I want to be able to write to the program's stdin whenever I want, get its stdout to go somewhere else (some file, buffer, I do not care) that I can easily retrieve later after an arbitrary amount of time with cat, tail or some other command with ssh.

call "ssh" in system function in perl

i have a question related to connecting via ssh with "system()" function in perl.
in my perl script i want to connect via ssh to another ip, run a command and return its value or redirect result value to a file.
system ("su - anotherUSer ; ssh someUsername#someIpAddress");
(i change my username so that i am not asked for a password)
when i execute this only line it changes the username correctly but not connects via ssh. In other words, the second part of the system call is not done (or is done but not reflected on the terminal).
If i enter mannualy to the server where this script executes and run this two commands, i can run them without errors.
When i run "exit" command to logout my anotherUser user an error raises:
(ssh: "username"."ip": node name or service name not known)
I also tested it escaping '#' and '.'
system ("su - anotherUSer ; ssh someUsername\#number\.number\.number\.number");
in this case when i run the "exit" command, it askes for the password(Remember that i swiched users so that password could be ommited).
I hope you understand my problem.
Thanks!!!
You're telling the wrong shell to execute ssh.
You spawn a shell and ask it to execute two commands, su and ssh. It first spawns su, which launches another shell. You didn't tell this new shell to do anything, so it waits for input. When it finally exits, the first shell executes the second command, ssh.
Use:
system("su -c 'ssh someUsername#someIpAddress' - anotherUSer");
But that's nasty! Why not just set up a key for the current user instead of becoming anottherUSer to use theirs?

How to supply an input value to the prompt via shell script?

I am writing a wrapper shell script wrapper.sh to run bunch of other already available scripts owned by other people and I cannot touch those scripts.
The problem is, there is one script that runs some db specific activities - db_perf_clean.sh. That script is normally executed manually and it prompts for a password at run time. There is no way I can supply the password to it as a parameter and I cannot modify that script. As such I know the db password and I can provide it in wrapper.sh.
Please let me know how can I run that db_perf_clean.sh script inside wrapper.sh like in a silent mode.
Sometimes a script will insist that a password be read from the tty. Often, it will read from stdin. If so, try:
echo password | db_perf_clean.sh
The above has the disadvantage that the password will appear in ps. To avoid that, hide the password in a file and use that file for stdin:
db_perf_clean.sh <file_with_password
If you want the command to be silent, you can throwaway its output:
db_perf_clean.sh <file_with_password >/dev/null 2>&1
Under bash, as opposed to generic shell, that can be slightly simplified:
db_perf_clean.sh <file_with_password &>/dev/null
I found out little different approach instead of writing a password in a file and that worked too ->
db_pass="somevalue"
sh db_perf_clean.sh<<EOM
$db_pass
EOM

Running Multiple Remote Commands Consecutively Through Matlab system()

I'd like to execute multiple commands consecutively using a matlab system call. I would first like to ssh into a remote machine then run a program on that machine. After the program starts I would like to then enter another command into this program's console. Here is what I would like to do in code:
system('ssh othermachine')
system('command on other machine')
%%WAIT FOR PROGRAM TO START RUNNING ON OTHER MACHINE
system('run command on other machine')
The problem is that Matlab will hang on the first system call and won't proceed to the next system call until the process form the first is exited. Is there a way around this?
Thanks for your help!
Prologue: Your problem is general and not just related to matlab.
When you want to run remote commands via ssh, they have to be issued in the ssh call. In a (linux) shell, you'd have
$ ssh remotemachine command1
for a single command. Hence, using a matlab system call you would have
>> system('ssh remotemachine command1').
When you want multiple commands to be executed sequentially, in a shell you'd write
$ ssh remotemachine "command1; command2"
i.e., in matlab, you'd write something like
>> system('ssh remotemachine "command1; command2"').
In general, is way more elegant to group your commands in a shell script, say script.sh, and pipe it in the ssh call
$ cat script.sh | ssh remotemachine
which, in matlab shell, sounds like
>> system('cat script.sh | ssh remotemachine').
There are a number of flags you can add in order to specify which behavior you want (e.g. in terms of session detachment/background execution, output collection,... look e.g. here).

Resources