iLO3: Multiple SSH commands - linux

is there a way to run multiple commands in HPs integrated Lights-Out 3 system via SSH? I can login to iLO and run a command line by line, but I need to create a small shell-script, to connect to iLO and to run some commands one by one.
This is the line I use, to get information about the iLO-version:
/usr/bin/ssh -i dsa_key administrator#<iLO-IP> "version"
Now, how can I do something like this?
/usr/bin/ssh -i dsa_key administrator#<iLO-IP> "version" "show /map1 license" "start /system1"
This doesn't work, because iLO thinks it's all one command. But I need something to login into iLO, run these commands and then exit from iLO. It takes too much time to run them one after the other because every login into iLO-SSH takes ~5-6 seconds (5 commands = 5*5 seconds...).
I've also tried to seperate the commands directly in iLO after manual login but there is no way to use multiple commands in one line. Seems like one command is finished by pressing return.
iLO-SSH Version is: SM-CLP Version 1.0
The following solutions did NOT work:
/usr/bin/ssh -i dsa_key administrator#<iLO-IP> "version; show /map1 license; start /system1"
/usr/bin/ssh -i dsa_key administrator#<iLO-IP> "version && show /map1 license && start /system1"

This Python module is for HP iLO Management. check it out
http://pypi.python.org/pypi/python-hpilo/

Try putting your commands in a file (named theFile in this example):
version
show /map1 license
start /system1
Then:
ssh -i dsa_key administrator#iLO-IP < theFile
Semicolons and such won't work because you're using the iLO shell on the other side, not a normal *nix shell. So above I redirect the file, with newlines intact, as if you were typing all that into the session by hand. I hope it works.

You are trying to treat iLO like it's a normal shell, but its really HP's dopy interface.
That being said, the easiest way is to put all the commands in a file and then pipe it to ssh (sending all of the newline characters):
echo -e "version\nshow /map1 license\nstart /system1" | /usr/bin/ssh -i dsa_key administrator#<iLO-IP>

That's a messy workaround, but would you might fancy using expect? Your script in expect would look something like that:
# Make an ssh connection
spawn ssh -i dsa_key administrator#<iLO-IP>
# Wait for command prompt to appear
expect "$"
# Send your first command
send "version\r"
# Wait for command prompt to appear
expect "$"
# Send your second command
send "show /map1 license\r"
# Etc...
On the bright side, it's guaranteed to work. On the darker side, it's a pretty clumsy workaround, very prone to breaking if something goes not the way it should (for example, command prompt character would appear in version output, or something like that).

I'm on the same case and wish to avoid to run a lot of plink commands. So I've seen you can add a file with the -m option but apparently it executes just one command at time :-(
plink -ssh Administrator#AddressIP -pw password -m test.txt
What's the purpose of the file ? Is there a special format for this file ?
My current text file looks like below:
set /map1/oemhp_dircfg1 oemhp_usercntxt1=CN=TEST
set /map1/oemhp_dircfg1 oemhp_usercntxt2=CN=TEST2
...
Is there a solution to execute these two commands ?

I had similar issues and ended up using the "RIBCL over HTTPS" interface to the iLO. This has advantages in that it is much more responsive than logging in/out over ssh.
Using curl or another command-line HTTP client try:
USERNAME=<YOUR_ILO_USERNAME>
PASSWORD=<YOUR_ILO_PASSWORD>
ILO_URL=https://<YOUR_ILO_IP>/ribcl
curl -k -X POST -d "<RIBCL VERSION=\"2.0\">
<LOGIN USER_LOGIN=\"${USERNAME}\" PASSWORD=\"${PASSWORD}\">
<RIB_INFO MODE="READ">
<GET_FW_VERSION/>
<GET_ALL_LICENSES/>
</RIB_INFO>
<SERVER_INFO MODE=\"write\">
<SET_HOST_POWER HOST_POWER=\"Yes\">
</SERVER_INFO>
</LOGIN>
</RIBCL>" ${ILO_URL}
The formatting isn't exactly the same, but if you have the ability to access the iLO via HTTPS instead of only ssh, this may give you some flexibility.
More details on the various RIBCL commands and options may be found at HP iLO 3 Scripting Guide (PDF).

Related

How can I ingore whitespaces inside an echo command when usual methods don't seem to work

Hi I'm pretty new to linux/bash in general and I'm having a some trouble making a script for my coworker. Idea of this script is to help automate coworkers IP table entries (don't use IP tables myself so no idea how it works, just working as per his instructions). Program is going to ask a few questions, form an entry and then add it to a file on a different host. After the file is written it will also run
"systemctl reload iptables.service" and "systemctl status iptables". I tested that pwd was atleast working where I was planning to put these.
The code worked fine with a single word in place of table_entry variable, I was able to write something to a file in my host computer with a different user.
Problem is that the "table_entry" variable is going to have whitespaces in it and the sudo su -c command gets the second word as input (atleast that's what I think is happening) and I get an error sudo: INPUT: command not found. the "INPUT" coming from my case sentence
I tried to put the "table_entry" variable in "{$table_entry}" , "$table_entry" and {$table_entry} forms but they didn't work.
I removed some of the code to make it more readable (mostly case sentences for variables and asking for host and username).
#!/bin/bash
echo -e "Which ports?
1. INPUT
2. OUTPUT
3. Forward"
read opt_ch
case $opt_ch in
1) chain="INPUT" ;;
2) chain="OUTPUT" ;;
3) chain="FORWARD" ;;
*) echo -e "Wrong Option Selected!!!"
esac
table_entry="-A $chain "#-s $ip_source -d $ip_dest
ssh -t user#host "sudo table_entry=$table_entry su -c 'echo $table_entry >> /home/user/y.txt'"
#^ this line will later also include the systemctl commands separated with ";" ^
I tested few different methods how to do this script overall, heredoc(didn't get input to work very well), Ansible(Didn't really seem like a great tool for this job), Python(can't install new modules to the enviroment). So this is the best solution I came up with bearing my limited skillset.
Edit: I also realise this is propably not the smartest way to do this script, but it's the only one I have gotten to work this far, that can also ask for a password from the user when doing su command. I'm not knowledgeable in transferring passwords safely in linux enviroment or in general, so I like to let linux handle the passwords for me.
This a problem with dealing with nested quoting - which is really quite the annoying problem to solve.
This case seems like you could do this with quotes inside the string - your example would become
ssh -t user#host "sudo table_entry='$table_entry' su -c 'echo \"$table_entry\" >> /home/user/y.txt'"
It seems to me the table_entry='$table_entry' is redundant though, this should work:
ssh -t user#host "sudo su -c 'echo \"$table_entry\" >> /home/user/y.txt'"
Your comment (denoted with #) is getting concatenated with the table_entry string you're trying to form. Try adding a space like this:
table_entry="-A $chain " #-s $ip_source -d $ip_dest
Then table_entry gets assigned correctly. I was using KWrite to edit your bash script, and it does text highlighting that quickly showed me the problem.

Simple commands not found bash (#!/usr/bin/expect)

I've recently started using bash to automate a windows rescue disk with chntpw. I'm trying to set up the program to use the expect command to listen for certain chntpw dialog questions and input the right answers without any user input. For some reason after setting up the bash script to use #!/usr/bin/expect rather than #!/bin/bash then many standard terminal commands are no longer understood.
I'm running the script by typing this into terminal:
user#kali:~/Desktop/projects/breezee$ bash breezee1.sh
The terminal output is as follows:
BREEZEE 1.0
Welcome to BREEZEE
breezee1.sh: line 9: fdisk: command not found
[Select] /dev/:
Here is my code:
#!/usr/bin/expect
clear
echo "BREEZEE 1.0"
echo "Welcome to BREEZEE"
fdisk -l
#list partitions
echo -n "[Select] /dev/:"
#ask user to choose primary windows partition
read sda
clear
echo /dev/$sda selected
umount /dev/$sda
sudo ntfsfix /dev/$sda
sudo mount -t ntfs-3g -o remove_hiberfile /dev/$sda /mnt/
cd /mnt/Windows/System32/config
clear
chntpw -l SAM #list accounts on windows partition
chntpw -u Administrator SAM
#now supply chntpw with values to run the password clear (this answers the prompts)
expect '> '
send '1\r'
expect '> '
send '2\r'
expect '> '
send '3\r'
expect ': '
send 'y\r'
expect '> '
send 'q\r'
expect ': '
send 'y\r'
clear
echo "Operation Successfull!"
chntpw -l SAM #list accounts on windows partition
In short, I'm trying to use standard bash/terminal commands alongside the expect commands. I'm probably going about this all wrong, so please correct me as I've been troubleshooting this for about three days and haven't gotten far :(
When you specify the application that should run your script, you can only use the scripting language that application will understand.
Clearly, Expect is not bash, and does not understand bash commands.
i suggest you separate those two scripts. Write the first part for !#/bin/bash, the second for Expect. Make the first script invoke the second script and redirect it to chntpw.
expect uses tcl not bash. So you can write your script in TCL when you use #!/usr/bin/expect.
For example, echo "BREEZEE 1.0" should be written as:
puts "BREEZEE 1.0"
And you should use exp_send instead of send.
From expect manual:
exp_send is an alias for send. If you are using Expectk or some other variant of Expect in the Tk environment, send is defined by Tk for an entirely different purpose. exp_send is provided for compatibility between environments. Similar aliases are provided for other Expect's other send commands.

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.

Pass a password to ssh in pure bash

I want to pass a password to ssh using a bash script (Yes, I know that there are ssh keys that I could use, but this is not what I intend).
I found some solutions that were using expect but since it is not a standard bash tool I am wondering if I can do this using pipes.
Can someone explain to me, why exactly something like this:
echo "password\n" | ssh somehost.com
or
ssh somehost.com <(echo "password\n")
doesn't work? Is there any possibility to make it work? Maybe executing ssh as a different process, obtaining its PID and then sending a string directly to it?
You can not specify the password from the command line but you can do either using ssh keys or using sshpass as suggested by John C. or using a expect script.
To use sshpass, you need to install it first. Then
sshpass -f <(printf '%s\n' your_password) ssh user#hostname
instead of using sshpass -p your_password. As mentioned by Charles Duffy in the comments, it is safer to supply the password from a file or from a variable instead of from command line.
BTW, a little explanation for the <(command) syntax. The shell executes the command inside the parentheses and replaces the whole thing with a file descriptor, which is connected to the command's stdout. You can find more from this answer https://unix.stackexchange.com/questions/156084/why-does-process-substitution-result-in-a-file-called-dev-fd-63-which-is-a-pipe
Since there were no exact answers to my question, I made some investigation why my code doesn't work when there are other solutions that works, and decided to post what I found to complete the subject.
As it turns out:
"ssh uses direct TTY access to make sure that the password is indeed
issued by an interactive keyboard user." sshpass manpage
which answers the question, why the pipes don't work in this case. The obvious solution was to create conditions so that ssh "thought" that it is run in the regular terminal and since it may be accomplished by simple posix functions, it is beyond what simple bash offers.

Linux: using the tee command via ssh

I have written a Fortran program (let's call it program.exe) with does some simulation for me. Via ssh I'm logging ino some far away computers to start runs there whose results I collect after a few days. To be up-to-date how the program proceeds I want to write the shell output into a text file output.txt also (since I can't be logged in the far away computers all the time). The command should be something like
nohup program.exe | tee output.txt > /dev/null &
This enables me to have a look at output.txt to see the current status even though the program hasn't ended its run yet. The above command works fine on my local machine. I tried first with the command '>' but here the problem was that nothing was written into the text file until the whole program had finish (maybe related to the pipe buffer?). So I used the workaround with 'tee'.
The problem is now that when I log into the computer via ssh (ssh -X user#machine), execute the above command and look at output.txt with the VI editor nothing appears until the program has finished. If I omit the 'nohup' and '&' I will not even get any shell output until it has finished. My thought was that it might have to do something with data being buffered by ssh but I'm rather a Linux newbie. For any ideas or workaround I would be very grateful!
I would use screen utility http://www.oreillynet.com/linux/cmd/cmd.csp?path=s/screen instead of nohup. Thus I would be able to set my program to detached state (^A^D) reconnect to the host, retrieve my screen session (screen -r)
and monitor my output as if I never logged out.

Resources