I'm writing a jython code which use Jsch to run some shell instructions on a remote machine. I need to wait a specific shell instruction has finished before continuing the exectuion of the jython code on my local machine (=need to synchronize shell code on a remote machine).
To do that, when the specific shell instruction has finished i create a text file in the remote machine. Then in my jython code I open an sftp channel and try periodically to get the file (using the sftp.exception and a "while true" loop). The code wait until the file is downloaded.
My problem is that even when the file is created, the jsch function "get" doesn't manage to download the file and keep sending "sftp.exception : no such file or directory" .That makes me locked up in an infinite loop.
Here is my code :
#We generate the info files for each class of the classlist
for classname in classlist:
print ("Generating information file (format : .out) for the class %s " % (classname))
#We open a shell channel and run the commands "windchill shell" and then "InfoReport.sh classname".
channel_generate = gl_session.openChannel('shell')
ops = channel_generate.getOutputStream()
ps = PrintStream(ops, True)
channel_generate.connect()
ps.println("windchill shell")
ps.println('rm ' + self.wt_home + '/tmp/' + classname + '.txt')
#The following instruction is the one i need to synchronize
ps.println(self.wt_home + '/bin/' + self.command + " " + classname)
#I create a file to detect the end of the previous instruction
ps.println('echo ok > ' + self.wt_home + '/tmp/' + classname)
ps.println('exit')
ps.close()
#Here we wait until the synchro file is created.
#We connect an sftp server and test every 4 seconds if we can retrieve the file.
channel_synchro = gl_session.openChannel('ftp')
channel_synchro.connect()
#This loop is broken when the get is successful
while True:
try:
channel_synchro.get(self.wt_home + '/tmp/' + classname,'/home/dev/temp')
break
except jsch.SftpException:
time.sleep(4)
#Disconnect and close de sftp channel
channel_synchro.disconnect()
channel_synchro.close()
#Disconnect and close the shell channel
channel_generate.disconnect()
channel_generate.close()
I have tried different solutions : other type of loops, create a new channel in each iteration of the "while true" loop, i have thought about user rights problem, i have checked if the paths are exact and they are, i have checked if the sftp function of my machine works and it works.
Nothing works, i'm still not able to solve this problem
Related
if(os.contains("windows"))
{
File bat = new File(System.getenv("APPDATA") + "/SelfCommandPrompt", appId + "-run.bat");
bat.getParentFile().mkdirs();
List<String> list = new ArrayList(1);
list.add("#echo off");
list.add("start" + " \"" + appName + "\" " + command);
IOUtils.saveFileLines(list, bat, true);
ProcessBuilder pb = new ProcessBuilder(bat.getAbsolutePath());
//inherit IO and main directory
pb.directory(getProgramDir());
//fire the batch file
pb.start();
System.exit(0);
}
So I dynamically create a .bat file and I want to run the process but, NOT IN THE BACKGROUND. Java forces the process to happen in the background how do I make it so it's not in the background? I am not looking to get the output stream from the .bat file I only want to execute it with the native gui it's intended to use on double click. Everywhere I look on these forums it only tells me how to do it in the background and get the outputstream? Why isn't there a boolean for this in the process builder? For my program specifically right now I want to reboot my java program with command prompt terminal on double click. I have the command generation working I tested the .bat file but, java again forces it to happen in the background.
Another use for doing a process not in the background. A java launcher for a game which executes a program with the gui not in the background which I may also need in the future.
Also the bat files output which is dynamically generated based off of the enviorment
java -Dfile.encoding=Cp1252 -cp C:\Users\jredfox\Documents\MDK\md5-spreadsheet\filededuper\bin;C:\Users\jredfox\Documents\MDK\md5-spreadsheet\filededuper\libs\apache-codecs.jar jredfox.selfcmd.SelfCommandPrompt true jredfox.filededuper.Main
edit I figured out a command for windows but, only windows. I need commands for mac
Runtime.getRuntime().exec("cmd /c start" + " \"" + appName + "\" " + command);
Figured it out.
basically get the terminal string on linux you need to make an api for it
save any shell scripts you need in the appdata
make an api to get the app data folder
create your custom command
return if conditions are not met like the System.console != null for my thing yours will be different.
execute command in new terminal window therefore the new native terminal using os commands.
All the code is found here.
https://github.com/jredfox/OpenTerminal
I'm using net.neoremind.sshxcute SSH Java API library to connect to a sftp server and execute a shell script present on that server.
My Shell Script does a simple job of moving files from that SFTP location to a HDFS location on some other machine.
Currently, there's no way to report if any of the files are not moved due to any reason such as connection failure, file with illegal name, empty file etc.
I wonder, how can I show that set of information for each failed file move from shell command back to Java code ?
This is my sample code :
// e.g sftpScriptPath => /abc/xyz
// sftpScriptCommand => sudo ./move.sh
// arguments => set of arguments to shell script.
task = new ExecShellScript(sftpScriptPath, sftpScriptCommand, arguments);
result = m_SshExec.exec(task);
if(result.isSuccess && result.rc == 0)
{
isSuccessful = true;
s_logger.info("Shell script executed successfully");
s_logger.info("Return code : " + result.rc);
s_logger.info("Sysout : " + result.sysout);
}
else
{
isSuccessful = false;
s_logger.info("Shell script execution failed");
s_logger.info("Return code : " + result.rc);
s_logger.info("Sysout : " + result.sysout);
}
The Result object returned from the exec method call includes:
exit status or return code (Result.rc),
standard output (stdout) (Result.sysout),
standard error (stderr) (Result.error_msg), and
an indication of success, based on return code and output (Result.isSuccess).
So, if you are committed to the current method of executing a shell script using the sshxcute framework, then the simplest way would be to have the move.sh script provide information about any failures while moving files. This could be done via a combination of return codes and standard output (stdout) and/or standard error (stderr) messages. Your Java code would then obtain this information from the returned Result object.
I am trying to automate some processes that were build in ancient times, for the sake of avoiding repetitive actions. It is required that the processes are started with one batch and stopped with another (this can not be changed btw).
So i made a commandline tool to do this (and many other repetitive stuff) and I have modelled a command that starts the 'startbatch' and a command that start the 'stopbatch'. Both commands work fine separatly (as I tested them separatly) but there seems to be a problem when i want execute them one after another (in the correct order ofcourse). I get the following error in new cmd.exe window:
The process cannot access the file because it is being used by another process.
the code that i am using to start the batches looks like this:
public void startBatchInDev(String company){
String startBatchFolder = locations.getLocationFor("startbatch");
try{
Runtime runtime = Runtime.getRuntime();
runtime.exec("cmd.exe /C cd \"" + startBatchFolder + "\" & start cmd.exe /k \"" + BATCHSTART + company.toLowerCase()+ "-dev" + BATCH_SUFFIX + "\"");
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
public void stopBatchInDev(String company){
String startBatchFolder = locations.getLocationFor("startbatch");
try{
Runtime runtime = Runtime.getRuntime();
runtime.exec("cmd.exe /C cd \"" + startBatchFolder + "\" & start cmd.exe /k \"" + BATCHSTOP + company.toLowerCase()+ "-dev" + BATCH_SUFFIX + "\"");
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
The names of the batchfiles are concatenated, but they are OK once the application is running.
The error message is quite clear, some file is locked and I can't access it because of it. Some googling confirms my suspicion, but I can't seem to find a solution for this. The hits in google are all about obvious uses of files, like an obvious shared resource. But in my case, i am not working on the same batch file. The stop and start batch are two different files. So I am actually starting to think that it might be the cmd.exe file that is being locked by windows...
So this question is actually two questions:
- what is the exact cause of the described problem?
- how do i programmatically fix this (if possible)?
thanks in advance!
So, basically, bat is not so great :-(
I was able to repro this from java, but I also found that this script:
#echo off
echo STOP
echo STOP >> E:\tmp\java\logfile.txt
C:\cygwin\bin\sleep.exe 1
echo STOP1 >> E:\tmp\java\logfile.txt
C:\cygwin\bin\sleep.exe 1
echo STOP2 >> E:\tmp\java\logfile.txt
When run twice like this:
start test.bat && start test.bat
Will fail with one or more messages like:
The process cannot access the file because it is being used by another process.
The reason is that " >> " redirection opens the file for Read/Write access but only FILE_SHARE_READ sharing. If two different programs attempt to open the file this way, one of them fails.
So, you cannot have two different batch files running at the same time and logging to the same file
I am writing a small Scala script to generate PGP signatures for all the files in the current directory. This is what I wrote:
object PGPSign {
def main(args: Array[String]) {
signFilesInDirectory(new java.io.File("."))
}
def signFilesInDirectory(dir: java.io.File) {
if(!dir.exists())
throw new java.io.FileNotFoundException
if(!dir.isDirectory())
throw new RuntimeException("Expecting directory")
println("Signing files in: " + dir.getAbsolutePath())
for{ file <- dir.listFiles
if !file.isDirectory //ignoring directories
val fileName = file.getName()
if !fileName.startsWith(".") //ignoring hidden files
} {
("gpg -ab " + fileName).!!
}
}
}
In the console, the command gpg -ab FILE_NAME will request a password. When I execute my scala script I got this exception at the point of invoking the external command:
gpg: cannot open tty `/dev/tty': Device not configured
Exception in thread "main" java.lang.RuntimeException: Nonzero exit value: 2
at scala.sys.package$.error(package.scala:27)
at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.slurp(ProcessBuilderImpl.scala:131)
at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.$bang$bang(ProcessBuilderImpl.scala:101)
at PGPSign$$anonfun$signFilesInDirectory$3.apply(PGPSign.scala:25)
at PGPSign$$anonfun$signFilesInDirectory$3.apply(PGPSign.scala:20)
at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:743)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:34)
at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:38)
at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:742)
at PGPSign$.signFilesInDirectory(PGPSign.scala:20)
at PGPSign$.main(PGPSign.scala:11)
at PGPSign.main(PGPSign.scala)
I have the idea this is related to the fact that the external command (gpg in this case) requests some input.
If this is what is creating the problem(?), what is the easiest general way to make any external command (requesting any amount of inputs) to work when executed from Scala ?
gpg expects to be able to read from/write to a tty, which is not available unless gpg is started from an interactive shell. You should use the --no-tty option to disable this behavior. Also, you probably want batch mode, enabled with --batch.
I am currently writing a CGI script that has an end goal of running a java program and then redirecting to a different page. However, the CGI causes a 500 internal server error when I call try to run the java program. I've tried os.system("[command]") and call(["command"]) and subprocess.Popen("command") and all three cause the same issue to crop up. Any suggestions are greatly appreciated.
Edit Also, the apache log gives me next to no information saying only that there is an invalid header.
Edit
#!/usr/bin/python
# Import the CGI module
import cgi
import random
import os
import sys
import re
import subprocess
# Required header that tells the browser how to render the HTML.
print "Content-Type: text/html\n\n"
form = cgi.FieldStorage()
userID = random.random()
print "<html>"
print "<title>Results</title>"
print "<body>"
command = "java [classname] "
user_id = random.randint(0, sys.maxint)
command += str(user_id) + " "
command += re.sub(r'\s', '', form['key0'].value) + " "
command += form['key1'].value + " "
command += form['key2'].value + " "
command += form['key3'].value + " " if form.has_key('key3') else "0 "
## This is where the problem exists
#os.system("ls -l")
#call(["ls", "-l"])
#p = subprocess.Popen(command)
## End of Problem
print command
print "<br>"
print "Redirecting..."
print "<meta http-equiv='refresh' content='0;url=",
print "http://192.168.1.41/Path/",
print user_id,
print ".html' />"
print "</body>"
print "</html>"
the entire command is not there, but I believe it is built correctly because I can copy the printed command out and run it in a terminal and it runs perfectly. The command is simply java [classname] [9 args]
the java code runs smoothly outside of the python code and all it does is generate a .png file and a .html file containing the .png. The name of the file is [user_id].html, hence the redirect.
the internal server error does not occur if only the process commands are commented out.
EDIT Ended up giving up and moving to php to execute this script. Thanks for all the help!
## This is where the problem exists
#os.system("ls -l")
#call(["ls", "-l"])
#p = subprocess.Popen(command)
## End of Problem
Focus on subprocess.Popen. Discard all others. Permanently. They're all bad ideas.
If subprocess.Popen(command) really does work as a stand-alone short Python script, then you have to investigate whether or not the Apache CGI-bin username has the required privileges to run this. Remember. Apache doesn't run as you. It runs as a separate "person" with separate privileges.
Your java command is probably spewing data into sys.stdout and or sys.stderr. If so, that output goes to Apache. Ideally, some stuff has already gone to Apache via sys.stdout which is a proper header and everything's good.
However, because of the way things are buffered, there's a small chance that Apache has seen no useable response and the java output is confusing.
I'd suggest that you switch to mod_wsgi instead of CGI because it's easier to control.
I'd also suggest that you capture the subprocess output in a file and then copy that file to sys.stdout so that Apache can't be confused by the java subprocess.
Have you tried:
import cgitb
cgitb.enable()
to get a more meaningful error - python error message in your browser
or
running your script from the command line on your server to see if python is returning an error, and if so, if it helps to diagnose the problem?
or
printing your java call as html output from your python script?