plink in PowerShell to run commands on Linux machine (SuSE) - linux

I am trying to automate the process of adding extra storage in a linux machine. I'm using plink in PowerShell installed on my Windows machine.
Below is the code:
$plinkpath = "C:\Users\mydrive\Modules\plink.exe"
if (Test-Path $plinkpath) {
Set-Alias plink $plinkpath
} else {
throw "Plink.exe is reqruied"
}
$passw = "linuxadmin$123"
$commands = #(
"sudo su;",
"pvcreate /dev/sde;",
"vgcreate test_vog /dev/sde",
"lvcreate -l 100%FREE -n test_lev test_vog;",
"mkfs.ext3 /dev/test_vog/test_lev;",
"mkdir /azurenew;",
"echo ""/dev/test_vog/test_lev /azurenew/ ext3 defaults 1 1"" >> /etc/fstab;",
"mount /azurenew/;"
)
Approach 1: Using .ppk file
plink -ssh -i "C:\Users\amurthy\Documents\WindowsPowerShell\Modules\sshprivate.ppk" linuxadmin#xx.xx.xx.xxx $commands
In the above situation PowerShell hangs and no response on the console. Not sure what's happening.
Approach 2: using direct log in
plink -P "22" -v "linuxadmin#xx.xx.xx.xxx" -pw "linuxadmin$123" $commands
Here, I get below response on console
Using username "linuxadmin".
Sent password
Password authentication failed
I do not understand why the passoword authentication failed though I am able to login using putty.exe with that password.
Can anyone please help me here to solve my above automation problem? If you have any better solution altogether really welcome.

The password login attempt fails because you defined the password in a double-quoted string. PowerShell tries to expand the (undefined) variable $123 in linuxadmin$123, so you're actually passing just linuxadmin as the password. You could use a single-quoted string to avoid this, but public key authentication (your first approach) is the better approach anyway, so I recommend sticking with that.
I'm not sure why your first approach causes the console to hang, though. If the key were password-protected you should be prompted for the password. There's a semicolon missing at the end of "vgcreate test_vog /dev/sde", but if that caused an issue I'd expect to see an error message.
Try running plink with the parameter -v (verbose messages) to get a better picture of what's going on.

Related

Telnet to server, login, and return command result in one line

I've looked at several other solutions, but none appear to be working the way I need.
I have an embedded controller running Linux (Dreadnaught) and a router also running Linux. I want to read the routing table (just the WAN IP of the default route) of the router, from the controller. My controller has telnet and wget, but does not have ssh or curl. I'd like to do this in a single command with a single result, so I can send the one command from an internal program and parse/save one result.
If I telnet to the router from my PC, either of these two commands gives me the exact result I need:
route |grep default|cut -c 17-32
or
dbctl get route/default/current_gateway
Route takes about 30 seconds (not sure why?), even without grep and cut; but dbctl is instant for all intents and purposes.
I've tried the eval method per Telnet to login with username and password to mail Server, but that shows all the telnet interactions; I want just the final string result.
I had a poke around at wget, but it looks to be for downloading files, not executing commands.
I'm hoping for:
somecommand server=1.2.3.4 user=myuser passwd=MyP#s$ command='dbctl get route/default/current_gateway'
which just returns:
8.7.6.5
Then my internal program (ISaGRAF, but shouldn't be relevant) can send one string to cmd and be returned 1 string, which I can use for my own nefarious purposes (well, I'm just going to log it actually).
If there's absolutely no other way, I can drop a sh script on to the requesting controller, but I'd rather not (extra steps to install, not as portable).
Solved as I was reviewing the question, but looking for suggestions - is this the cleanest method? Could it be done better?
OK, I poked around at the eval method again. Yes, it shows me the full interaction, but it's easy to just get the bits I need, using head and tail:
eval "{ sleep 2; echo myuser; sleep 1; echo MyP#s$; sleep 1; echo 'dbctl get route/default/current_gateway'; sleep 2; }" |telnet 1.2.3.4 |head -n 5|tail -n 1
eval returns the full interaction:
Entering character mode Escape character is '^]'.
login: myuser
Password:
admin#myrouter:~# dbctl get route/default/current_gateway
8.7.6.5
admin#myrouter:~#
So I just need head and tail to grab the one line I want using |head -n 5|tail -n 1

Shebang causes script to fail

I'm quite bad at bash, and I try to make a script to connect to all my switches with openSSH in order to make some configuration.
I created an array containing all my 25 switches, and then I used a loop to open SSH connection with each of them.
As I'm on Windows and using bash, I've just installed Cygwin.
However, I had to use expect and writing my password in plain text as the switches are quite poor and that is the best way for me (I won't manually put my RSA key on every single switch as it would take me as much time as writing manually the configuration on every switch).
I use the shebang #!/usr/bin/expect -f to make bash recognize expect. When I do this, the expect syntax (spawn, expect, interact) works perfectly, but my array doesn't work.
I get the following error message:
extra characters after close-quote
while executing "arrayname=("172.21.21.20" "172.20.55.55" ... "
When I change the shebang, and use #!/bin/bash, expect is not found anymore :
./stationsnmp.sh: line 20: spawn : command not found couldn't read
./stationsnmp.sh: line 24: send : command not found couldn't read
file "assword": no such file or directory ./stationsnmp.sh: line 27:
send : command not found ./stationsnmp.sh: line 28: interact :
command not found
I'm really not a pro in bash, which explains I can't get this little problem... Some help would be welcome.
EDIT : Below is a part of my code
#!/bin/bash
switch=("172.20.0.229" "172.20.0.232" "172.20.0.233" "172.21.0.15" "172.21.0.16" "172.21.2.1" "172.20.2.250" "172.21.3.1" "172.20.3.250" "172.21.4.1" "172.20.4.250" "172.21.6.1" "172.20.6.250" "172.21.7.1" "172.20.7.250" "172.21.8.1" "172.20.8.250" "172.20.9.250" "172.21.9.1" "172.21.10.1" "172.20.10.250" "172.21.11.1" "172.20.11.250" "172.21.12.1" "172.21.12.250")
nmb=`echo ${#switch[#]}`
set timeout 3
for ((ii=0; ii<=$nmb; ii++))
#for ii in {0..${#switch[#]}}
do
if [ ${switch[$ii]:5:1} -eq 1 ]
then
ipdc=`echo ${switch[ii]} | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.'`"10"
spawn ssh admin#switch[$ii]
expect "*assword*"
send "PASS\r"
interact
exit
fi
done
You are mixing bash and expect, those are two entirely different languages. You probably want to have a bash wrapper script with proper option handling (see getopts) which takes a list of IP addresses and execute your expect script for each IP address passed to your bash-wrapper. If your expect script is small you might want to embed it into your shell script as opposed to having it in a separate file.
EDIT:
#!/bin/bash
switches=("172.20.0.229" "172.20.0.232")
for ip in "${switches[#]}"; do
expect "${ip}" <<-'EOT'
set host [lindex $argv 0]
set timeout 3
spawn ssh -l admin $host
expect "*assword*"
send "PASS\r"
interact
exit
EOT
done

how to parse password during the find command in linux?

I need to parse password during find a file in remote linux system, how can I read a remote directory in linux?
I tried one:
ssh root#192.168.5.6 "find /var/www/home" sshpass -p pass
it didn't work properly in linux, if any one face this solution, please let me know...
I tried two:
opendir(IN, "root#192.168.5.6:/var/www/home") || die "can't open !";
I tring also perl but it didn't work properly,
How can I start? How can I read a remote directory?
use Net::SFTP::Foreign.
use Net::SFTP::Foreign;
my $sftp = Net::SFTP::Foreign->new($host, user => $user, password => $password, autodie => 1);
my $ls = $sftp->ls($dir);
use Data::Dumper;
print Dumper($ls);
It wont work that way in perl. Try something like this:
open(IN, "$cmd|")
where $cmd is the command that works for you from the command line.

Nagios verify Sharepoint

I want to set Nagios (on my Debian) to verify a SharePoint server is up. I already tried to use cURL but it didn't worked for some issue that I don't know so I decided to change the way I'll verify that service.
It's simple in theory, I just have to make a script to send an request (http or https, doesn't matter) and check the response, if is 200 for successful or 40x if not (ok at this point).
So I have to use telnet or any ftp service to do that or I can use another feature/tool for that.
With telnet I'am having problem with 400 error. SharePoint returns this error when server is up or down, so I don't work for me.
Any ideas??
You can use the check_http plugin of Nagios. For example:
check_http -H SharepointHostname/IP -p port
You can use the -S flag for secure http connections
You can use the -u flag for going to specific URL
You can use the -s flag to search for a specific string in the HTML page returned from the url specified with the -u flag.
So basically you can request a specific page, scan for a known String, and if successfully found, you are sure this page is up (which means server is up etc.)
Example:
check_http -H my.sharepoint.com -u /start/page/sharepoint.aspx -s "test string"
Commonly this is done on login pages etc. Don't forget to escape special chars in your URL, if it contains any (like ? and &).
There's also a perl script available for checking sharepoint servers.
Does this not do what you want:
http://exchange.nagios.org/directory/Plugins/Email-and-Groupware/Microsoft-Sharepoint/check_sharepoint-2Epl/details
Most likely you're going to need a login/password for Sharepoint in order to monitor much more than the basic IIS / website is working.
I done my own way to check if SharePoint is UP or DOWN. Please pay attention that this script just checks the service status, nothing more like user permissions or whatever.
Perl script:
#!/usr/bin/env perl
use strict;
use warnings;
use LWP::UserAgent;
use Getopt::Long qw(:config no_ignore_case_always auto_version);
GetOptions ('h=s' => \my $h);
my $ua = LWP::UserAgent->new;
$ua->agent('Mozilla/4.0 (compatible; MSIE 5.0; Windows 95)');
my $req = $ua->get('http://' . $h);
my $retorno = '';
if ($req->is_success)
{
$retorno = $req->content;
}
else
{
$retorno = $req->status_line;
}
if ($retorno eq "401 Unauthorized")
{
print "OK: SharePoint service at " . $h . " server is UP.";
exit 0;
}
else
{
print "CRITICAL: SharePoint service at " . $h . " server is DOWN.";
exit 2;
}
In case you got this exception when you run the script:
Can't locate LWP/UserAgent.pm in #INC
this article may help you as it helped me:
http://help.directadmin.com/item.php?id=274
So in Nagios commands.cfg file you'll declare the command this way:
command_line /usr/local/nagios/libexec/check_sharepoint.pl -h $HOSTADDRESS$
Where $HOSTADDRESS is the host IP variable in Nagios scope.
Remember to chmod +x on the file. I know you will...

How to write a bash script to give another program response

I have a bash script that does several tasks, including python manage.py syncdb on a fresh database. This command asks for input, like the login info for the admin. Currently, I just type this into the command line every time. Is there a way I can automatically provide these replies as part of the bash script?
Thanks, I don't really know anything about bash.
I'm using Ubuntu 10.10.
I answered a similar question on SF, but this one is more general, and it's good to have on SO.
"You want to use expect for this. It's probably already on your machine [try which expect]. It's the standard tool for any kind of interactive command-line automation. It's a Tcl library, so you'll get some Tcl skills along the way for free. Beware; it's addictive."
I should mention in this case that there is also pexpect, which is a Python expect-alike.
#!/path/to/expect
spawn python manage.py syncdb
expect "login:*"
send -- "myuser\r"
expect "*ssword:*"
send -- "mypass\r"
interact
If the program in question cannot read the input from stdin such as:
echo "some input" | your_progam
then you'll need to look to something like expect and/or autoexepect
You can give defaults values to the variables. In line 4 and 5, if the variables RSRC and LOCAL aren't set, they are set to those default values. This way you can give the options to your script or use the default ones
#!/bin/bash
RSRC=$1
LOCAL=$2
: ${RSRC:="/var/www"}
: ${LOCAL:="/disk2/backup/remote/hot"}
rsync -avz -e 'ssh ' user#myserver:$RSRC $LOCAL
You can do it like this, given an example login.py script:
if __name__ == '__main__':
import sys
user = sys.stdin.readline().strip()
passwd = sys.stdin.readline().strip()
if user == 'root' and passwd == 'password':
print 'Login successful'
sys.exit(0)
sys.stderr.write('error: invalid username or password\n')
sys.exit(1)
good-credentials.txt
root
password
bad-credentials.txt
user
foo
Then you can do the login automatically using:
$cat good-credentials.txt | python login.py
Login successful
$cat bad-credentials.txt | python login.py
error: invalid username or password
The down-side of this approach is you're storing your password in plain text, which isn't great practice.

Resources