pexpect - run script.sh over ssh - shell

I'm having trouble programmatically running a local script over ssh.
I'm unsure if this is a problem with the shell variable substitution on the local host.
When manually running,
ssh monit#server1 'bash -s' < /u02/splunk/splunk/etc/apps/Splunk_TA_nix/bin/cpu.sh
I get the expected output,
CPU pctUser pctNice pctSystem pctIowait pctIdle
all 11.21 0.00 1.50 0.31 86.98
0 0.00 0.00 0.00 0.00 100.00
1 3.00 0.00 1.00 0.00 96.00
....
but I get
bash: /u02/splunk/splunk/etc/apps/Splunk_TA_nix/bin/cpu.sh: No such file or directory
when running the following code,
splunk_bin_dir = '/u02/splunk/splunk/etc/apps/Splunk_TA_nix/bin'
hostname = 'server1'
username = 'monit'
password = 'monit#_'
command = "/usr/bin/ssh %(username)s#%(hostname)s 'bash -s' < %(splunk_bin_dir)s/cpu.sh" % locals()
print command
ssh_new_conn = 'Are you sure you want to continue connecting'
p = pexpect.spawn(command, timeout=360)
# Handles the 3 possible connection outcomes:
# a) Ssh to the remote host for the first time, triggering 'Are you sure you want to continue connecting'
# b) ask you for password
# c) No password is needed at all, because you already have the key.
i = p.expect([ssh_new_conn,'[pP]assword:',pexpect.EOF])
print ' Initial pexpect command output: ', i
if i == 0:
# send 'yes'
p.sendline('yes')
i = p.expect(['[pP]assword:',pexpect.EOF])
print 'sent yes. pexpect command output', i
if i == 0:
# send the password
p.sendline(password)
p.expect(pexpect.EOF)
elif i == 1:
# send the password
p.sendline(password)
p.expect(pexpect.EOF)
elif i == 2:
print "pexpect faced key or connection timeout"
pass
print p.before
These are the printed outputs,
/usr/bin/ssh monit#server1 'bash -s' < /u02/splunk/splunk/etc/apps/Splunk_TA_nix/bin/cpu.sh
Initial pexpect command output: 1
bash: /u02/splunk/splunk/etc/apps/Splunk_TA_nix/bin/cpu.sh: No such file or directory
pexpect is bumping into the [pP]assword line so I guess the password is being correctly passed,

Here the note from pexpect manual:
Remember that Pexpect does NOT interpret shell meta characters such as
redirect, pipe, or wild cards (>, |, or *). This is a common mistake.
If you want to run a command and pipe it through another command then
you must also start a shell.
This is the working line
command = """/bin/bash -c "/usr/bin/ssh %(username)s#%(hostname)s 'bash -s' < %(splunk_bin_dir)s/cpu.sh" """ % locals()

Related

How I combine a bash hookscript with a Perl hookscript for use with Proxmox?

I am trying to use Promox VE has the hypervisor for running VMs.
In one of my VMs, I have a hookscript that is written for the bash shell:
#!/bin/bash
if [ $2 == "pre-start" ]
then
echo "gpu-hookscript: Resetting GPU for Virtual Machine $1"
echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/remove
echo 1 > /sys/bus/pci/rescan
fi
which is to help with enabling GPU passthrough.
And then I have another hookscript that is written in Perl, which enables virtio-fs:
#!/usr/bin/perl
# Exmple hook script for PVE guests (hookscript config option)
# You can set this via pct/qm with
# pct set <vmid> -hookscript <volume-id>
# qm set <vmid> -hookscript <volume-id>
# where <volume-id> has to be an executable file in the snippets folder
# of any storage with directories e.g.:
# qm set 100 -hookscript local:snippets/hookscript.pl
use strict;
use warnings;
print "GUEST HOOK: " . join(' ', #ARGV). "\n";
# First argument is the vmid
my $vmid = shift;
# Second argument is the phase
my $phase = shift;
if ($phase eq 'pre-start') {
# First phase 'pre-start' will be executed before the guest
# ist started. Exiting with a code != 0 will abort the start
print "$vmid is starting, doing preparations.\n";
system('/var/lib/vz/snippets/launch-virtio-daemon.sh');
# print "preparations failed, aborting."
# exit(1);
} elsif ($phase eq 'post-start') {
# Second phase 'post-start' will be executed after the guest
# successfully started.
print "$vmid started successfully.\n";
} elsif ($phase eq 'pre-stop') {
# Third phase 'pre-stop' will be executed before stopping the guest
# via the API. Will not be executed if the guest is stopped from
# within e.g., with a 'poweroff'
print "$vmid will be stopped.\n";
} elsif ($phase eq 'post-stop') {
# Last phase 'post-stop' will be executed after the guest stopped.
# This should even be executed in case the guest crashes or stopped
# unexpectedly.
print "$vmid stopped. Doing cleanup.\n";
} else {
die "got unknown phase '$phase'\n";
}
exit(0);
What would be the best way for me to combine these two files into a single format, so that I can use it as a hookscript in Proxmox?
I tried reading the thread here about how to convert a bash shell script to Perl, and not being a programmer, admittedly, I didn't understand what I was reading.
I appreciate the teams help in educating a non-programmer.
Thank you.
before
system('/var/lib/vz/snippets/launch-virtio-daemon.sh');
insert pls.
system('echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/remove');
system('echo 1 > /sys/bus/pci/rescan');
Had your original code above evaluated return code of these perl calls (it is not the case):
echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/remove
echo 1 > /sys/bus/pci/rescan
you could apply solutions from:
Getting Perl to return the correct exit code

How do you get user input when running a fish script from a url?

Consider this fish script :
#!/usr/bin/fish
while true
read -l -P "Give me an answer [y/n]:" reply
switch $reply
case Y y
return 0
case '' N n
return 1
end
end
When run from the command line using :
$ ./script-name.fish
It works just as expected with the script waiting for you to answer y or n.
However when I upload to a url and attempt to run it using :
$ curl http://path.to/script-name.sh | fish
It gets stuck in a permanent loop, how do I run this script from a url and allow for user input?

Difference in behavior between shell and script

I have a set of commands that I am attempting to run in a script. To be exact, the lines are
rm tmp_pipe
mkfifo tmp_pipe
python listen_pipe.py &
while [ true ]; do nc -l -w30 7036 >>tmp_pipe; done &
listen_pipe.py is simply
if __name__ == "__main__":
f = open("tmp_pipe")
vals = " "
while "END" not in vals:
vals = f.readline()
if len(vals) > 0:
print(vals)
else:
f = open("tmp_pipe")
If I run the commands in the order shown I get my desired output, which is a connection to an ESP device that streams motion data. The connection resets after 30 seconds if the ESP device leaves the network range or if the device is turned off. The python script continues to read from the pipe and does not terminate when the tcp connection is reset. However, if I run this code inside a script file nc fails to connect and the device remains in an unconnected state indefinitely. The script is just
#!/bin/bash
rm tmp_pipe
mkfifo tmp_pipe
python listen_pipe.py &
while [ true ]; do nc -l -w30 7036 >>tmp_pipe; done &
This is being run on Ubuntu 16.04. Any suggestions are greatly welcomed, I have been fighting with this code all day. Thanks,
Ian

I want to use parallel-ssh to run a bash script on multiple servers, but it simple prints the echo statements

I have a bash script called sr_run_batch.sh which does super resolution of images. Now I want to do testing on different servers in parallel at the same time. ie. 1 Virtual machine at one given point of time. then 2 virtual machines at one point of time , 3 and then 4.
I tried writing into it the commands
for host in $(cat hosts.txt); do ssh "$host" "$command" >"output.$host"; done
ssh-keygen && for host in $(cat hosts.txt); do ssh-copy-id $host; done
where the file hosts.txt contains the list of servers: username#ip(format) but when I run this, it gives me substitution error
Hence, I tried pssh (parallel-ssh)
pssh -h hosts-file -l username -P $command
command being ./sr_run_batch.sh
but it didn't run, so I modified this to
pssh -h hosts-file -l ben -P -I<./sr_run_batch.sh
But, for some unknown reason, it just prints the echo statements in the code.
here is the code :
NList=(5)
VList=(1)
FList=("input/flower1.jpg" "input/flower2.jpg" "input/flower3.jpg" "input/flower4.jpg")
IList=("320X240" "640X480" "1280X960" "1920X1200")
SList=(2 3)
for VM in ${VList[#]}; do
for ((index=0; index < ${#FList};)) do
file=$FList[$index]
image_size=$IList[$index]
width=`echo $image_size|cut -d "X" -f1`
height=`echo $image_size|cut -d "X" -f2`
for scale_factor in ${SList[#]}; do
for users in ${NList[#]}; do
echo "V: $VM, " "F: $file, " "S: $scale_factor, " "I: $width $height , " "N: $users"
for i in `seq 1 $users` ; do
./sr_run_once.sh $file $width $height $scale_factor &
done
wait
done # for users
done # for scale_factor
done # for index
done # for VM
exit 0
Have you also tried to use pssh with a simple bash-script so see if the communication is set up ok?
$ pssh -h hosts.txt -A -l ben -P -I<./uptime.sh
Warning: do not enter your password if anyone else has superuser
privileges or access to your account.
Password:
10.0.0.67: 11:06:50 up 28 min, 2 users, load average: 0.00, 0.00, 0.00
[1] 11:06:50 [SUCCESS] 10.0.0.67
10.0.0.218: 11:06:50 up 24 min, 2 users, load average: 0.00, 0.05, 0.20
[2] 11:06:50 [SUCCESS] 10.0.0.218

error in pexpect script to login as root

import pexpect, os, sys
cmd = "sudo su -"
p = pexpect.spawn(cmd, timeout=60)
pass_expect = ".*assword.*" (as I get a prompt saying "[sudo] password for user" )
p.expect(pass_expect)
print "I want the password"
p.sendline("mypassword")
p.logfile = sys.stdout
p.sendline("logout")
p.close()
I am getting the following error while executing the above script
Error
Traceback (most recent call last):
File "test.py", line 11, in
p.expect(pass_expect)
File "/usr/lib/python2.6/dist-packages/pexpect.py", line 1311, in expect
return self.expect_list(compiled_pattern_list, timeout, searchwindowsize)
File "/usr/lib/python2.6/dist-packages/pexpect.py", line 1325, in expect_list
return self.expect_loop(searcher_re(pattern_list), timeout, searchwindowsize)
File "/usr/lib/python2.6/dist-packages/pexpect.py", line 1409, in expect_loop
raise TIMEOUT (str(e) + '\n' + str(self))
pexpect.TIMEOUT: Timeout exceeded in read_nonblocking().
version: 2.3 ($Revision: 399 $)
command: /usr/bin/sudo
args: ['/usr/bin/sudo', 'su', '-']
searcher: searcher_re:
0: re.compile(".*assword.*")
buffer (last 100 chars): root#:~#
before (last 100 chars): root#:~#
after:
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 16933
child_fd: 3
closed: False
timeout: 60
delimiter:
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
Can someone please help me out as I am been stuck in this problem from few days.
Any help will be appreciated.
Thanks !!
If you login as a superuser means put root#localhost
child = pexpect.spawn("ssh root#localhost")
child.logfile = open("/tmp/mylog", "w")
child.expect(".*assword:")
child.send("guest\r")
child.expect(".*\$ ")
child.sendline("python -V\r")
print child.before
How to login the super user(root) in remote host system using pexpect?

Resources