How to invoke a java program with classpath from Python 3.x - python-3.x

I am trying to execute an external java program from a python 3.7 program using the java command with classpath. I am using subprocess.Popen module in Python. Somehow I am not able to get it working! Appreciate any assistance!
cmd = ['java',
'-classpath', 'C:/Users/Documents/MqTransfer.jar', 'C:/Users/Documents/com.ibm.mq.commonservices.jar',
'C:/Users/Documents/com.ibm.mq.headers.jar', 'C:/Users/Documents/com.ibm.mq.jar',
'C:/Users/Documents/com.ibm.mq.jmqi.jar', 'C:/Users/Documents/com.ibm.mq.pcf.jar',
'C:/Users/Documents/connector.jar', 'C:/Users/Documents/xerces.jar',
'MyMqTransfer', 'C:/Users/Documents/queueTransfer.properties']
jproc = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE)
output, errors = jproc.communicate()
print(output, errors)
I am getting the below error
b'' b'Error: Could not find or load main class C:.Users.Documents.com.ibm.mq.commonservices.jar\r\n'
When I try to run the java program from my batch script it runs fine! This is the command I use in my batch script. The issue is with my python code!
java -classpath MqTransfer.jar;com.ibm.mq.commonservices.jar;com.ibm.mq.headers.jar;com.ibm.mq.jar;com.ibm.mq.jmqi.jar;com.ibm.mq.pcf.jar;connector.jar;xerces.jar com.ibm.my.mq.MyMqTransfer C:\Users\Documents\queueTransfer.properties

Based on the error, I believe the process being executed is something like 'java -classpath C:/Users/Documents/MqTransfer.jar c:/Users/Documents/com.ibm.mq.commonServices.jar [followed by the rest of the arguments you are passing to process]' such that java is passed MqTransfer.jar as the entire classpath argument and thinks 'C:.Users.Documents.com.ibm.mq.commonservices.jar' is your class to launch. Try combining your entire intended classpath into the 3rd argument of your launch and I think you will be good. It would look something like this:
cmd = ['java',
'-classpath', 'C:/Users/Documents/MqTransfer.jar;C:/Users/Documents/com.ibm.mq.commonservices.jar;C:/Users/Documents/com.ibm.mq.headers.jar;C:/Users/Documents/com.ibm.mq.jar;C:/Users/Documents/com.ibm.mq.jmqi.jar;C:/Users/Documents/com.ibm.mq.pcf.jar;C:/Users/Documents/connector.jar;C:/Users/Documents/xerces.jar',
'MyMqTransfer', 'C:/Users/Documents/queueTransfer.properties']

Related

Execute Python script using Laravel?

I'm trying to execute a python script in a Laravel 5.8 project but I'm having problems with the Symfony/process class.
Basically, I want to run this python script that takes an excel form from the storage folder.
My first try was this
$process = new Process('C:\Python\python.exe C:\Users\"my path"\laravel\storage\app\images\cargaExcel.py');
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
echo $process->getOutput();
And the error is
Fatal Python error: _Py_HashRandomization_Init: failed to get random numbers to initialize Python
I also tried with shell_exec(), and if the two files (the excel and the python script are in the public path - app/public) it works.
I think the problem is that python only executes on the app/public folder, so I don't know how to run this in another path.
Python output is telling me that:
Working directory: C:\Users\"my path"\laravel\public
Does anyone know how to run this?
You can pass the working directory as the second argument of the process class
So it can be:
$process = new Process('C:\Python\python.exe C:\Users\"my path"\laravel\storage\app\images\cargaExcel.py', "/my/working/path/");
Also you may pass command as array
$process = new Process(['C:\Python\python.exe', 'C:\Users\"my path"\laravel\storage\app\images\cargaExcel.py'], "/my/working/path/");

python subprocess call from wsgi

When I run the exact same function from the python3 interpreter vs, apache via mod wsgi, they both run error free but one returns the command text from apache the stout is simply always blank. Again I am running the exact same function.
Backgorund, I want to run svn update on some code to do so I am using subprocess to simply call "svn update /path/to/repo"
def update():
p1=subprocess.Popen(["svn", "update", "/var/www/myrepocode"],stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
(ret, stderr) = p1.communicate(timeout=10)
return (str(ret.decode('utf-8')))
when i run from the python3 shell or another python 3 script called from the shell
from test import update
print(update())
it works fine and i get
"Updating '/var/www/myrepocode':\nAt revision 27.\n"
when I have a wsgi script and execute it from accessing the web page
def application(environ, start_response):
...
output = output + "---"+update() +"---"
...
response_headers = [('Content-type', 'text/html'), ('Content-Length',
str(len(output)))]
start_response(status, response_headers)
return [output.encode('utf-8')]
I get an empty string:
------
I do not have a python virtual environment, just normal python3 and there are no errors thrown either. I suspect this has to do with the user running it but I really don't know. setting shell=True doesn't change anything either. Any help is greatly appreciated.
Your update method does not return nor print stderr . Maybe you should check for errors first by adding the following line in the update method.
print(stderr)
If errors are produced, can you post them?

Scala.js - pass command line arguments from SBT run

When running the app using the sbt run while developing normal JVM app, I can pass command line arguments using run <args>. When I try the same with Scala.js, I get an error "No valid parser available". When trying runMain variant like runMain Main.main arg, the error is "Expected non-whitespace character", with arrow pointing just behind Main.main.
Is there some way how to pass arguments to the Scala.js / Node.js application when running it from SBT?
(I am using Scala.js 0.6.15).
No, there isn't, because JavaScript does not have a notion of command-line arguments. Node.js does, but only if started from the command-line, and that use case is not supported by the sbt plugin, I'm afraid.
Feel free to file a feature request. I'm not sure it can be accommodated, but we can look into it eventually.
One can define a custom task calling node.js, and parse arguments using SBT parsers. Add this into build.sbt:
import complete.DefaultParsers._
lazy val runa = inputKey[Unit]("Run app with arguments")
runa := {
(fastOptJS in Compile).value // build it first
val args: Seq[String] = spaceDelimited("<arg>").parsed
val npmRun = "node index.js" + args.map("\"" + _ + "\"").mkString(" "," ","")
npmRun.!
}
You also need to create a file index.js in your project root, containing something like this:
require("./target/scala-2.12/xxxx-jsdeps.js");
require("./target/scala-2.12/xxxx-fastopt.js");
In the intervening years, a library has emerged to address this:
https://ben.kirw.in/decline/

Groovy Postbuild do not execute scripts on Jenkins

I've written simple groovy script, but I don't know how to execute it on Jenkins.
Look at this simple script:
String jbN = System.getenv('JOB_NAME')
println jbN
println "Hello"
I would except that I will reveived at least "Hello". Script give no return. I've just received Build step 'Groovy Postbuild' marked build as failure(or success)
It seems that script is not executed.
EDIT:
I didn't add it, but I have already script which will analize logs, so I need it to execute it post-build.
The problem is bigger then I thought. Plugins: "Scriptler" or "Groovy Plugin" do not print anything.
Script which I'm trying to print out:
String jbN = System.getenv('JOB_NAME')
println jbN
I found the solution:
Script was executed but wasn't printed to console output.
To print result to console output you need to write:
manager.listener.logger.println("Some string") instead of println.
To make it shorter do:
logger = manager.listener.logger.&println
// and call like this:
logger("test log message")
EDIT: add in logger example and to describe how to get env vars (and how to not get them) and to hopefully save people some debugging time . . . this is simple but awkward stuff.
To get the workspace you can go through the manager object. Like this:
manager.build.workspace
To get env vars, this does not work:
String jbN = System.getenv('JOB_NAME')
It shows jbN is null.
That makes sense as JOB_NAME is not an actual system environment var.
This also does not work to get env vars, an exception is thrown:
${manager.envVars['WORKSPACE']}
This does work to get jenkins job "env vars" like WORKSPACE, JOB_NAME, BUILD_NAME:
def build = Thread.currentThread().executable
workspace = build.getEnvVars()["WORKSPACE"]
Example of use, you can call a groovy script in workspace like this:
evaluate(new File(manager.build.workspace.toString() + "/dirinworkspace/scriptname.groovy"))
In your case you want to use the Groovy plugin rather than the Groovy Postbuild plugin.
The Groovy Postbuild plugin is made to change the build result (postbuild).
The Groovy plugin is made to run simple Groovy scripts inside your job.
Click Manage Jenkins-->Script Console

How do you get the path of the running script in groovy?

I'm writing a groovy script that I want to be controlled via a properties file stored in the same folder. However, I want to be able to call this script from anywhere. When I run the script it always looks for the properties file based on where it is run from, not where the script is.
How can I access the path of the script file from within the script?
You are correct that new File(".").getCanonicalPath() does not work. That returns the working directory.
To get the script directory
scriptDir = new File(getClass().protectionDomain.codeSource.location.path).parent
To get the script file path
scriptFile = getClass().protectionDomain.codeSource.location.path
As of Groovy 2.3.0 the #SourceURI annotation can be used to populate a variable with the URI of the script's location. This URI can then be used to get the path to the script:
import groovy.transform.SourceURI
import java.nio.file.Path
import java.nio.file.Paths
#SourceURI
URI sourceUri
Path scriptLocation = Paths.get(sourceUri)
Note that this will only work if the URI is a file: URI (or another URI scheme type with an installed FileSystemProvider), otherwise a FileSystemNotFoundException will be thrown by the Paths.get(URI) call. In particular, certain Groovy runtimes such as groovyshell and nextflow return a data: URI, which will not typically match an installed FileSystemProvider.
This makes sense if you are running the Groovy code as a script, otherwise the whole idea gets a little confusing, IMO. The workaround is here: https://issues.apache.org/jira/browse/GROOVY-1642
Basically this involves changing startGroovy.sh to pass in the location of the Groovy script as an environment variable.
As long as this information is not provided directly by Groovy, it's possible to modify the groovy.(sh|bat) starter script to make this property available as system property:
For unix boxes just change $GROOVY_HOME/bin/groovy (the sh script) to do
export JAVA_OPTS="$JAVA_OPTS -Dscript.name=$0"
before calling startGroovy
For Windows:
In startGroovy.bat add the following 2 lines right after the line with
the :init label (just before the parameter slurping starts):
#rem get name of script to launch with full path
set GROOVY_SCRIPT_NAME=%~f1
A bit further down in the batch file after the line that says "set
JAVA_OPTS=%JAVA_OPTS% -Dgroovy.starter.conf="%STARTER_CONF%" add the
line
set JAVA_OPTS=%JAVA_OPTS% -Dscript.name="%GROOVY_SCRIPT_NAME%"
For gradle user
I have same issue when I'm starting to work with gradle. I want to compile my thrift by remote thrift compiler (custom by my company).
Below is how I solved my issue:
task compileThrift {
doLast {
def projectLocation = projectDir.getAbsolutePath(); // HERE is what you've been looking for.
ssh.run {
session(remotes.compilerServer) {
// Delete existing thrift file.
cleanGeneratedFiles()
new File("$projectLocation/thrift/").eachFile() { f ->
def fileName=f.getName()
if(f.absolutePath.endsWith(".thrift")){
put from: f, into: "$compilerLocation/$fileName"
}
}
execute "mkdir -p $compilerLocation/gen-java"
def compileResult = execute "bash $compilerLocation/genjar $serviceName", logging: 'stdout', pty: true
assert compileResult.contains('SUCCESSFUL')
get from: "$compilerLocation/$serviceName" + '.jar', into: "$projectLocation/libs/"
}
}
}
}
One more solution. It works perfect even you run the script using GrovyConsole
File getScriptFile(){
new File(this.class.classLoader.getResourceLoader().loadGroovySource(this.class.name).toURI())
}
println getScriptFile()
workaround: for us it was running in an ANT environment and storing some location parent (knowing the subpath) in the Java environment properties (System.setProperty( "dirAncestor", "/foo" )) we could access the dir ancestor via Groovy's properties.get('dirAncestor').
maybe this will help for some scenarios mentioned here.

Resources