JSCH setCommand is not working - jsch

No Exception comes and Command is also not making any work based on command mentioned.Here permisson of directory is not created and directory is also not created.Please give your suggestion.
Update :
channelexe.getExitStatus is added but problem is it gives -1, what is the meaning of this ?. I don't know how to find some explaination why command is not doing it's job(update 777 mode of fileDir1) .
String depDir = "/usr/local/FTPReceive/DEPLOYED/fileDir1";
log.info("updateDepositedFilePermission ........ starts");
Session session = new FTPComponent().getSession("");
Channel channel = null;
ChannelSftp channelSftp = null;
try
{
session.connect();
System.out.println("session is alive:" + session.isConnected());
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp) channel;
ChannelExec channelexe = (ChannelExec) session.openChannel("exec");
channelexe.setCommand("chmod 777 -R " + depDir);
channelexe.connect();
System.out.println("channelexe.getExitStatus:"+channelexe.getExitStatus());
}
catch (Exception e1)
{
e1.printStackTrace();
System.out.println("Manual Exception in updateDepositedFilePermission:" + CommonUtil.getExceptionString(e1));
}

channelexe.setCommand("chmod 777 -R " + depDir);
channelexe.setCommand("mkdir /usr/local/fileStore");
channelexe.connect();
A ChannelExec accepts a single command string to invoke on the remote system. Your second call to setCommand() is discarding the chmod command and replacing it with the mkdir command. Assuming the remote shell is bash or similar, you could use shell syntax to construct a command string which runs both commands:
String cmd = "chmod 777 -R " + depDir + " && mkdir /usr/local/fileStore";
channelexe.setCommand(cmd);
No Exception comes...
ChannelExec doesn't throw an exception when a command merely fails. You can call Channel.getExitStatus() to get the exit status of the remote command. The value will be 0 if chmod and mkdir succeeded, or non-zero if they failed. The channel also has functions to read the standard error of the remote command, which will permit you to read any error messages which they output.
The JSCH website has several example programs, including an example of executing a remote command.

Related

How to check SSH command execute or not in PHP?

I am running ssh command using phpseclib. Here if condition showing wrong message. How to check ssh command execution in if condition. My code is:
$command = "sudo rm /path/filename";
if(!$ssh->exec($command)){
$response['success'] = false;
$response['messages'] = 'File delete Failed';
}else{
$response['success'] = true;
$response['messages'] = 'File deleted';
}
Here file deleting successfully. The message only shows wrong. Pls help me in this

How to handle "no such file or directory" in expect script?

I have script that uses #!/usr/bin/expect to connect/disconnect to VPN.
But not all of my PCs configured similarly so VPN command can be at PATH but it also can be not.
My question is: how to handle moment when there is no such command in PATH. Script just stops when he tries to execute command that is not presented in PATH.
Here is script that I'm wrote so far:
#!/usr/bin/expect -d
set timeout -1
spawn vpn status
expect {
"Disconnected" {
expect eof
set timeout -1
spawn vpn connect <vpnurl>
expect "Username:"
send "username\r"
expect "Password:"
send "password\r"
expect eof
}
"Connected" {
expect eof
set timeout -1
spawn vpn disconnect
expect eof
}
"*" {
set timeout -1
spawn /opt/cisco/anyconnect/bin/vpn status
expect {
"Disconnected" {
expect eof
set timeout -1
spawn /opt/cisco/anyconnect/bin/vpn connect <vpnurl>
expect "Username:"
send "username\r"
expect "Password:"
send "password\r"
expect eof
}
"Connected" {
expect eof
set timeout -1
spawn /opt/cisco/anyconnect/bin/vpn disconnect
expect eof
}
}
}
}
And error that I receive when command not in PATH:
spawn vpn status
couldn't execute "vpn": no such file or directory
while executing
"spawn vpn status"
I tried to use which vpn and command -v vpn to check if vpn is here but they just don`t produce any output.
expect is a tcl extension, and tcl has a few options for trapping and handling errors: try and catch. Something along the lines of:
if {[catch {spawn vpn status} msg]} {
puts "spawn vpn failed: $msg"
puts "Trying again with absolute path"
spawn /path/to/vpn status
}
You can do the existence test in expect/tcl before attempting to spawn it:
foreach vpn {vpn /opt/cisco/anyconnect/bin/vpn} {
set path [auto_execok $vpn]
if {$path ne "" && [file executable $path]} {
set vpn_exec $path
break
}
}
if {$vpn_exec eq ""} {
puts stderr "vpn not executable: is it installed?"
exit 1
}
spawn $vpn_exec status
...
See
file
auto_execok

How to ask for a user input from a remote server with SSHKit?

I need to ask a user input from a ruby script on a remote server. I managed to perform it with bash with the following code
class ConfirmHandler
def on_data(command, stream_name, data, channel)
puts "data received: #{data}"
if data.to_s =~ /\?$/
prompt = Net::SSH::Prompt.default.start(type: 'confirm')
response = prompt.ask "Please enter your response (y/n)"
channel.send_data "#{response}\n"
end
end
end
require 'sshkit'
require 'sshkit/dsl'
include SSHKit::DSL
on '<ssh-server-name>' do |host|
cmd = <<-CMD
echo 'Do something?';
read response;
echo response=$response
CMD
capture(cmd.squish , interaction_handler: ConfirmHandler.new)
end
When I run this script on my local machine I see
data received: Do something?
Please enter your response (y/n)
data received: response=y
I try to wrap the bash CMD code into a ruby script:
on '<ssh-server-name>' do |host|
cmd = <<-CMD
ruby -e "
puts 'Do something?';
require 'open3';
response = Open3.capture3('read response; echo $response');
puts 'response=' + response.to_s;
"
CMD
capture(cmd.squish , interaction_handler: ConfirmHandler.new)
end
and get the following result:
data received: Do something?
Please enter your response (y/n)
data received: response=["\n", "", #<Process::Status: pid 9081 exit 0>]
I was writing the code above looking at the Interactive commands section on the SSHKit Github home page
How can I capture the user response from a ruby script with SSKKit on the remote server?
I was able to capture the user response from a ruby script on a remote server with the following code:
# ask_response.rb
puts 'Do something?';
response = `read response; echo $response`;
puts 'response=' + response.to_s;
ask_response.rb is a ruby script which is located on a remote server. And locally I run:
on '<ssh-server-name>' do |host|
capture("ruby ask_response.rb" , interaction_handler: ConfirmHandler.new)
end

Gulp task to SSH and then mysqldump

So I've got this scenario where I have separate Web server and MySQL server, and I can only connect to the MySQL server from the web server.
So basically everytime I have to go like:
step 1: 'ssh -i ~/somecert.pem ubuntu#1.2.3.4'
step 2: 'mysqldump -u root -p'password' -h 6.7.8.9 database_name > output.sql'
I'm new to gulp and my aim was to create a task that could automate all this, so running one gulp task would automatically deliver me the SQL file.
This would make the developer life a lot easier since it would just take a command to download the latest db dump.
This is where I got so far (gulpfile.js):
////////////////////////////////////////////////////////////////////
// Run: 'gulp download-db' to get latest SQL dump from production //
// File will be put under the 'dumps' folder //
////////////////////////////////////////////////////////////////////
// Load stuff
'use strict'
var gulp = require('gulp')
var GulpSSH = require('gulp-ssh')
var fs = require('fs');
// Function to get home path
function getUserHome() {
return process.env.HOME || process.env.USERPROFILE;
}
var homepath = getUserHome();
///////////////////////////////////////
// SETTINGS (change if needed) //
///////////////////////////////////////
var config = {
// SSH connection
host: '1.2.3.4',
port: 22,
username: 'ubuntu',
//password: '1337p4ssw0rd', // Uncomment if needed
privateKey: fs.readFileSync( homepath + '/certs/somecert.pem'), // Uncomment if needed
// MySQL connection
db_host: 'localhost',
db_name: 'clients_db',
db_username: 'root',
db_password: 'dbp4ssw0rd',
}
////////////////////////////////////////////////
// Core script, don't need to touch from here //
////////////////////////////////////////////////
// Set up SSH connector
var gulpSSH = new GulpSSH({
ignoreErrors: true,
sshConfig: config
})
// Run the mysqldump
gulp.task('download-db', function(){
return gulpSSH
// runs the mysql dump
.exec(['mysqldump -u '+config.db_username+' -p\''+config.db_password+'\' -h '+config.db_host+' '+config.db_name+''], {filePath: 'dump.sql'})
// pipes output into local folder
.pipe(gulp.dest('dumps'))
})
// Run search/replace "optional"
SSH into the web server runs fine, but I have an issue when trying to get the mysqldump, I'm getting this message:
events.js:85
throw er; // Unhandled 'error' event
^
Error: Warning:
If I try the same mysqldump command manually from the server SSH, I get:
Warning: mysqldump: unknown variable 'loose-local-infile=1'
Followed by the correct mylsql dump info.
So I think this warning message is messing up my script, I would like to ignore warnings in cases like this, but don't know how to do it or if it's possible.
Also I read that using the password directly in the command line is not really good practice.
Ideally, I would like to have all the config vars loaded from another file, but this is my first gulp task and not really familiar with how I would do that.
Can someone with experience in Gulp orient me towards a good way of getting this thing done? Or do you think I shouldn't be using Gulp for this at all?
Thanks!
As I suspected, that warning message was preventing the gulp task from finalizing, I got rid of it by commenting the: loose-local-infile=1 From /etc/mysql/my.cnf

Cisco VPN Client automatic login

I need to automate the login process of a Cisco VPN Client version 5.0.07.0440.
I've tried using a command line like this but there is something wrong:
vpnclient.exe connect MyVPNConnection user username pwd password
This starts the connection but then a User Authentication dialog is shown, asking for username, password and domain. Username and password are already filled, domain is not necessary.
To continue I must press the OK button.
Is there a way to not show the dialog and automatically login into the vpn?
Run vpnclient.exe /?:
That way just run
vpnclient.exe connect MyVPNConnection -s < file.txt
file.txt
username
password
Below worked for me Cisco AnyConnect Secure Mobility Client:
Try to connect to VPN for the first time using vpncli.exe and note every keystroke i.e every command, every enter( \n ) you press, username & password you enter.
Copy each command sequentially in .login_info file.
Sample .login_info:
connect unkbown.data-protect.com
\n
\n
KC23452
\n
Note: Replace \n with normal enter, these are the exact steps that I followed while connecting via vpncli.exe. Username and group-name were saved automatically that's the reason the 2nd and 3rd lines are \n ( enter ). Also, the last \n is required.
Go to C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client
Open CMD here
vpncli.exe -s < .login_info
First, we need to use the vpncli.exe command line approach with the -s switch.
It works from command line or script. If you were looking for a solution in C#:
//file = #"C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe"
var file = vpnInfo.ExecutablePath;
var host = vpnInfo.Host;
var profile = vpnInfo.ProfileName;
var user = vpnInfo.User;
var pass = vpnInfo.Password;
var confirm = "y";
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = file,
Arguments = string.Format("-s"),
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
}
};
proc.OutputDataReceived += (s, a) => stdOut.AppendLine(a.Data);
proc.ErrorDataReceived += (s, a) => stdOut.AppendLine(a.Data);
//make sure it is not running, otherwise connection will fail
var procFilter = new HashSet<string>() { "vpnui", "vpncli" };
var existingProcs = Process.GetProcesses().Where(p => procFilter.Contains(p.ProcessName));
if (existingProcs.Any())
{
foreach (var p in existingProcs)
{
p.Kill();
}
}
proc.Start();
proc.BeginOutputReadLine();
//simulate profile file
var simProfile = string.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}"
, Environment.NewLine
, string.Format("connect {0}", host)
, profile
, user
, pass
, confirm
);
proc.StandardInput.Write(simProfile);
proc.StandardInput.Flush();
//todo: these should be a configurable value
var waitTime = 500; //in ms
var maxWait = 10;
var count = 0;
var output = stdOut.ToString();
while (!output.Contains("state: Connected"))
{
output = stdOut.ToString();
if (count > maxWait)
throw new Exception("Unable to connect to VPN.");
count++;
Thread.Sleep(waitTime);
}
stdOut.Append("VPN connection established! ...");
(This might have extra stuff which is not required for you specific case.)
Here is a BAT script for automatic logon using Cisco AnyConnect Secure Mobility Client (version 4.10.03104):
taskkill -im vpnui.exe -f
"%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe" disconnect
SLEEP 3
"%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe" -s < credential.txt
SLEEP 8
"%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpnui.exe"
The file "credential.txt" must contain three lines:
connect <host>
<login>
<password>
where <host> is IP address or hostname of the host to connect, <login> is your login, and <password> is your password. The first line taskkill -im vpnui.exe -f is nesessary for killing the GUI, because when the GUI is running the login through the command line doesn't work. The last line launches the GUI again after successive logon.
The same script written as a VBS file (suitable for Windows Task Sheduler):
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "taskkill -im vpnui.exe -f"
WshShell.Run """%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe"" disconnect"
WScript.Sleep 3000
WshShell.Run "cmd /K ""%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe"" -s < credential.txt"
WScript.Sleep 8000
WshShell.Run """%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpnui.exe"""
Save this script as "login.vbs", and assign running it as an "Action" in the Windows Task Sheduler.