How to Execute Batch File Remotely in java? - java

I have to execute batch file present at remote machine from my local machine.
I am connecting through ftp to remote machine and try to execute batch file remotely.but not able to do that also not getiing any exception .below is my code
public static void main(String[] args) throws SocketException, IOException,
InterruptedException {
static String server = "192.168.2.133";
static int port = 21;
static String user = "kamal";
static String pass = "12345";
static FTPClient ftpClient;
// TODO Auto-generated method stub
ftpClient = new FTPClient();
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory("/");
System.out.println(ftpClient.isConnected());
// ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
System.out.println("ftpClient.printWorkingDirectory() "
+ ftpClient.printWorkingDirectory());
String[] str = ftpClient.listNames(ftpClient.printWorkingDirectory());
for (String string : str) {
System.out.println(string);
}
// ftpClient.changeWorkingDirectory(ftpClient.printWorkingDirectory().concat("demo"));
System.out.println("ftpClient.printWorkingDirectory() "
+ ftpClient.printWorkingDirectory());
String psCommand = "C:/Users/kamlesh.kumar/Downloads/PSTools/PsExec.exe //"
+ server + " -u " + user + " -p " + pass;
psCommand = psCommand + " " + "MEF.bat";
// psCommand = psCommand + " " + commandToRunOnRemoteMachine + " " +
// parameters;
String[] cmd = new String[5];
cmd[0] = "cmd.exe";
cmd[1] = "/C";
cmd[2] = psCommand;
cmd[3] = "";
cmd[4] = "";
// Run remote command
// ftpClient.changeWorkingDirectory(ftpClient.printWorkingDirectory().concat("\\\\192.168.2.135\\demo\\demo"));
// System.out.println(ftpClient.printWorkingDirectory());
File f = new File(ftpClient.printWorkingDirectory());
Process p = null;
try {
p = Runtime.getRuntime().exec(cmd, null, f);
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
int exitStatus = 0;
try {
exitStatus = p.waitFor();
System.out.println("exitStatus in try " + exitStatus);
} catch (Exception e) {
System.out.println("exitStatus" + exitStatus);
System.out.println(e.toString());
e.printStackTrace();
} finally {
System.out.println("exitStatus in finally " + exitStatus);
}
if (exitStatus == 0) {
System.out.println("Done");
}
}

You can get PSEXEC from https://technet.microsoft.com/en-us/sysinternals/pxexec.aspx and what I have done before was make a batch file that would copy the file you want ran on the remote pc to that PC then use PSEXEC to execute it remotly and also delete that file that was made. I do not know if that is what you're looking for but it might be sufficient.
set remotecpu="computer you're sending it to"
robocopy "localpcdrive\location1\scripts\script you want ran" \\%remotecpu%\c$\temp_folder
psexec \\%remotecpu% -u "username" -p "password" -i -d "C:\temp_folder\path to\script you want ran"
And if I am not mistaken that will execute the file for you then just do a del command and remove the temp_folder your script is under. Or use something fancy like
If Exist "%SystemDrive%\temp_folder" (RD/S/Q "%SystemDrive%\temp_folder")

Related

Is it possible to write a generic interactive ProcessBuilder client based on commands and breakpoints as input?

I need to write a generic interactive ProcessBuilder client based on commands and breakpoints to interact with the same python script several times.
The idea is that each (n+1) command (except n=0 ofc) will wait to read in the output stream the (n-1) breakpoint.
The client's output will be the output stream from the first command to the last one.
Ex of script:
def show_menu():
print('Select an option:' + '\n')
print('[1] Fullname')
print('[2] Username')
print('[3] Password')
def app_start():
show_menu()
try:
choice = int(input('\n' + 'Your selection: '))
app_start()
except KeyboardInterrupt:
sys.exit(0)
else:
if choice == 1:
input = input("Enter your fullname")
print(f'Your fullname is: {input}')
if choice == 2:
input = input("Enter your Username")
print(f'Your username is: {input}')
if choice == 3:
input = input("Enter your password: ")
print(f'Your password is : {input}')
def main():
app_start()
# Start Here
if __name__ == "__main__":
main()
Example of input to the Process builder client:
[
{
"cmd": "python3 C:\\pathToScript\\script.py",
"breakpoint": "Your selection:"
},
{
"cmd": "3\n",
"breakpoint": "Enter your password: "
},
{
"cmd": "John Doe\n",
"breakpoint": "Your password is: "
}
]
The Output of the client for this case will be:
[1] Fullname
[2] Username
[3] Password
Your selection: 3
Enter your password password123
Your password is: password123
Thanks in advance for any help, I'm new to Java and newer to ProcessBuilder :).
This seems to be working just fine, putting the thread to sleep for 100 ms is prob only a good idea for scripts that don't take long to execute though. If anyone sees caveats on this approach please feel free to leave a comment.
String actionCommands = "[\n" +
" {\n" +
" \"cmd\": \"python3 C:\\pathToScript\\script.py\" +
" \"breakpoint\": \"Your selection:\"\n" +
" },\n" +
" {\n" +
" \"cmd\": \"3\\n\",\n" +
" \"breakpoint\": \"Enter your password:\"\n" +
" },\n" +
" {\n" +
" \"cmd\": \"password123\\n\",\n" +
" \"breakpoint\": \"Your password is: \"\n" +
" }\n" +
" ]";
org.json.JSONArray arrayCmds = new org.json.JSONArray(actionCommands);
System.out.printf("arrayCmds %s\n", arrayCmds.toString());
Process process = null;
org.json.JSONObject objInit = arrayCmds.getJSONObject(0);
String cmdInit = objInit.getString("cmd");
ProcessBuilder processBuilder1 = new ProcessBuilder(cmdInit.split(" "));
processBuilder1.redirectErrorStream(true);
try {
process = processBuilder1.start();
Thread inThread = new Thread((Runnable) new In(process.getInputStream()));
inThread.start();
processBuilder1.inheritIO();
BufferedReader inputStream = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
OutputStream writeTo = process.getOutputStream();
for (int i = 1 ; i < arrayCmds.length(); i++) {
org.json.JSONObject obj = arrayCmds.getJSONObject(i);
org.json.JSONObject objBrkPt = arrayCmds.getJSONObject(i-1);
String cmd = obj.getString("cmd");
String breakpoint = objBrkPt.getString("breakpoint");
Thread.sleep(100);
while (((inputStream.readLine())!=null && inputStream.readLine()!=breakpoint))
{
writeTo.write(cmd.getBytes());
writeTo.flush();
break;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This is the implementation of the In class
public class In implements Runnable {
private InputStream is;
private List<String> out = new ArrayList<String>();
public In(InputStream is) {
this.is = is;
}
public List<String> output() {
return out;
}
#Override
public void run() {
byte[] b = new byte[1024];
int size = 0;
try {
while ((size = is.read(b)) != -1) {
out.add(new String(b));
System.err.println(new String(b));
}
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
there is something wront with implementation as it fails randomly in capturing the last part of the stream that contains the pwd

Runtime.exec() the executable library not work in non root

i have a code :
private static String writeCommandToConsole(Process proc, String command, boolean ignoreError) throws Exception {
byte[] tmpArray = new byte[1024];
proc.getOutputStream().write((command + "\n").getBytes());
proc.getOutputStream().flush();
int bytesRead;
if (proc.getErrorStream().available() > 0) {
if ((bytesRead = proc.getErrorStream().read(tmpArray)) > 1) {
Log.e(LOG_TAG, new String(tmpArray, 0, bytesRead));
if (!ignoreError)
throw new Exception(new String(tmpArray, 0, bytesRead));
}
}
if (proc.getInputStream().available() > 0) {
bytesRead = proc.getInputStream().read(tmpArray);
Log.i(LOG_TAG, new String(tmpArray, 0, bytesRead));
}
return new String(tmpArray);
}
public static void Changes(Context con, int fNums, String fNames, int is, boolean bools, String strs) {
final String fNum = String.valueOf(fNums);
final String fName = fNames;
final String i = String.valueOf(is);
final String str = strs;
final String bool = bools ? "true" : "false";
final String path = pathExecutable + " " + fNum + " \"" + fName + "\" " + i + " " + bool + " \"" + str + "\"";
new Thread(new Runnable() {
#Override
public void run() {
try {
if (isRoot) {
Process proc = Runtime.getRuntime().exec(new String[]{"su"});
writeCommandToConsole(proc, path, true);
} else {
Process proc = Runtime.getRuntime().exec(path);
proc.wait();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}
for root is work well (my phone is rooted) .. but for non root it not work (use parallel space, virtualXposed,etc in non root phone) .. in non root only work in virtual machine which have a root (vmos,x8 sabdbox etc).
i was try use processBuilder but have a same result .. executable lib seem not get into the target ..
how to write a correct runtime.exec to make it work on non root phone (use parallel space or any cloner without virtual machine with root include) ? or is it any way to make it posible to run executable lib without su command ?
solved .. i change non root command into
Process proc = Runtime.getRuntime().exec(new String[]{"sh"});
writeCommandToConsole(proc, path, true);
and it run well in some virtual app ..

MySql Database import is not working with java web application

I want to import mysql database using java on web application but unfortunately the mysql.exe process get stuck and next Line of code does not get executed which make browser to keep on loading.
restore.xhtml
<h:panelGrid columns="1" style="margin: 0 auto;">
<p:commandButton value="1 click restore"
action="#restoreBean.oneClickRestore()}" update="all,g" ajax="false"/>
</h:panelGrid>
RestoreBean.java
String absPath ="C:/Users/sms/build/web/resources/backup/backuproot.sql";
String[] executeCmd = new String[]{"mysql ", dbName, "-u " + dbUser, "-p " + dbPwd, "-e ", " \"source "+ absPath+" \""};
try{
Process runtimeProcess = Runtime.getRuntime().exec(executeCmd);
int processComplete = runtimeProcess.waitFor();// after this line no line of code get executed; in taskmanager u can see mysql.exe
if (processComplete == 0) {
restoreMsg = "Successfully restored from SQL : " + absPath;
} else {
restoreMsg = "Error at restoring";
}
} catch (InterruptedException ex) {
Logger.getLogger(RestoreBean.class.getName()).log(Level.SEVERE, null, ex);
}
But the same code runs well and database get imported when used in console application
RestoreDbTest.java
public class RestoreDbTest{
public static void main(String[] args) {
RestoreDbTest b = new RestoreDbTest();
b.restoreDatabase("root", "", "b.sql");
}
public boolean restoreDatabase(String dbUserName, String dbPassword, String source) {
String[] executeCmd = new String[]{"mysql ", dbName, "-u " + dbUser, "-p " + dbPwd, "-e ", " \"source b.sql \""};
Process runtimeProcess;
try {
runtimeProcess = Runtime.getRuntime().exec(executeCmd);
int processComplete = runtimeProcess.waitFor();
if (processComplete == 0) {
// log.info("Backup restored successfully with " + source);
return true;
} else {
//log.info("Could not restore the backup " + source);
}
} catch (Exception ex) {
System.out.println(ex.getCause());
}
return false;
}
}
mysql process list

Runtime - exec to dump database using mysqldump JAVA

I'm trying to use mysqldump with java to create a dump for my database.
I've done the code but the condition if(processCompleted == 0) never happens for some reason that I can not understand. And I say this because on the console there is no exception but it always prints
"Error doing dump!"
which leads me to conclude that if(processCompleted == 0) is never meet.
Can someone please explain me what I'm doing wrong here?
public boolean backupDatabase(String path, String whichServer)
{
String cmd;
Process runtimeProcess;
if(whichServer.equalsIgnoreCase("local"))
{
cmd = "mysqldump -u " + getSourceUsername() + " -p" + getSourceServerPassword()
+ " --add-drop-database -B " + getSourceDatabase() + " -r " + path;
}
else if(whichServer.equalsIgnoreCase("remote"))
{
cmd = "mysqldump -u " + getDestinationUsername() + " -p" + getDestinationServerPassword()
+ " --add-drop-database -B " + getDestinationDatabase() + " -r " + path;
}
else
{
System.out.println("Input server incorrect");
return false;
}
try{
String[] cmdArray = new String[]{"C:\\wamp\\bin\\mysql\\mysql5.5.24\\bin\\mysqldump.exe", cmd};
System.out.println("Preparing for dump.");
runtimeProcess = Runtime.getRuntime().exec(cmdArray);
int processCompleted = runtimeProcess.waitFor();
if(processCompleted == 0)
{
System.out.println("Dump done!");
return true;
}
else
{
System.out.println("Error doing dump!");
}
} catch(Exception ex)
{
System.out.println("Exception -> " + ex.getMessage());
}
return false;
}
Here's my code using #MadProgrammer suggestion:
public boolean backupDatabase(String path, String whichServer)
{
List<String> args = new ArrayList<String>();
args.add("C:\\wamp\\bin\\mysql\\mysql5.5.24\\bin\\mysqldump.exe");
args.add("-u");
args.add(getSourceUsername());
args.add("-p");
args.add(getSourceServerPassword());
args.add("--add-drop-database");
args.add("-B");
args.add(getSourceDatabase());
args.add("-r");
args.add(path);
try{
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectError();
Process p = pb.start();
InputStream is = p.getInputStream();
int in = -1;
while((in = is.read()) != -1)
{
System.out.println((char) in);
}
int proccessCompleted = p.waitFor();
if(proccessCompleted == 0)
{
System.out.println("Dump done!");
return true;
}
else
{
System.out.println("Error doing dump!");
return false;
}
}
catch(IOException | InterruptedException ex)
{
System.out.println("Exception exportDB -> " + ex.getMessage() + "|" + ex.getLocalizedMessage());
}
return false;
}
PS; where you wrote "//? Is this a single command?" -p is the command for the password and getSourceServerPassword() is the method to get the password.
I suspect because you've separated the cmdArray into only two elements that mysqldump is treating the second array element as a single command line argument.
Also, you've not paying attention to the output of the process which makes it really difficult for your to ascertain what the processing is trying to tell.
You "base" command also includes mysqldump...
"mysqldump -u " + getSourceUsername() + " -p" + getSourceServerPassword()
+ " --add-drop-database -B " + getSourceDatabase() + " -r " + path;
as part of the command, which means you are effectively calling mysqldump mysqldump...
Instead of using a String, place all your commands into some kind of list instead.
Remember, if it's separated by a space on the command line, it's a separate command/element
List<String> args = new ArrayList<String>
args.add("C:\\wamp\\bin\\mysql\\mysql5.5.24\\bin\\mysqldump.exe");
//...
args.add("-u");
args.add(getSourceUsername());
args.add("-p" + getSourceServerPassword()); //?? Is this a single command?
args.add("--add-drop-database");
args.add("-B");
args.add(getSourceDatabase());
args.add("-r");
args.add("path);
//...
Then use ProcessBuilder
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectError();
Process p = pb.start();
InputStream is = p.getInputStream();
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char)in);
}
int processCompleted = p.waitFor();
Remember, you should never ignore the output from a process, even if you don't care, you should attempt to consume the content from the InputStream as some processes will hang if there output stream is not read.

Creating a Shell Script to execute a Jar (which executes a sudo command)

so I wrote a Java program to change the IP of a machine.
public static void main(String[] args) {
superUserChangeIp(args);
}
public static void superUserChangeIp(String[] args) {
try {
String ethInterface = args[0].toString().trim();
String ip = args[1].toString().trim();
System.out.println(ethInterface + " " + ip);
String[] command = {
"/bin/sh",
"ifconfig " + ethInterface + " " + ip };
Process child = Runtime.getRuntime().exec(command);
changeNetworkInterface(ethInterface, ip);
readOutput(child);
child.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
I made a simple sh script :
#!/bin/sh
sudo java -jar changeip.jar $1 $2
and I'm getting : /bin/sh: 0: Can't open sudo ifconfig eth0 192.168.217.128 trying to run sh ipconfig.sh eth0 192.168.217.128
Anyone can point me to the right direction?
Note: the method changeNetworkInterface(ethInterface, ip); simply updates the settings found in /etc/network/interfaces, code follows :
protected static void changeNetworkInterface(String ethInterface, String ip) throws IOException {
String oldInterface = File.readFile(NETWORK_INTERFACES_PATH);
StringBuilder builder = new StringBuilder();
Scanner reader = new Scanner(oldInterface);
boolean startReplacing = false;
while (reader.hasNextLine()) {
String currentLine = reader.nextLine();
if (currentLine.contains("iface " + ethInterface)) {
System.out.println("Found interface!");
startReplacing = true;
}
if (startReplacing && currentLine.contains("address")) {
System.out.println("Found IP!");
currentLine = "address " + ip;
startReplacing = false;
}
builder.append(currentLine);
builder.append("\n");
}
System.out.println(builder.toString());
File.writeToFile(NETWORK_INTERFACES_PATH, builder.toString());
}
If you're running the JAR as you described, the application will already have superuser privileges, so you don't need to run sudo inside the app at all.
Really sorry; I just added -c
String[] command = {
"/bin/sh",
"-c", // <--- this bugger right here
"ifconfig " + ethInterface + " " + ip };
And now it works. Thanks everyone.

Categories