Ant sshexec task called from gradle doesn't show output - java

I want to use Apache ant sshexec task in my gradle custom task. The problem is that this task doesn't work (output is not shown in console and sshexec action is not executed). This is how I use it:
configurations {
sshexecAntTask
}
repositories {
mavenCentral()
}
dependencies {
sshexecAntTask 'org.apache.ant:ant-jsch:1.7.0'
}
// ----------------------------------------------------
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files
class MyCustomTask extends DefaultTask {
#TaskAction
def build() {
String command = ""
command = 'cmd.exe /C mdir C:\\aadd'
runSshCommand(command)
}
private void runSshCommand(String command) {
String host = "host"
String username = "username"
String password = "password"
ant.taskdef(name: 'sshexec', classname: 'org.apache.tools.ant.taskdefs.optional.ssh.SSHExec', classpath: project.configurations.sshexecAntTask.asPath)
// this command is not executed; why?
ant.sshexec(host: host, username: username, password: password, command: command, trust: 'true', failonerror: 'true')
}
}
[EDIT]
I've tested sshexec and those are my results:
The command cmd.exe /C echo test > C:\testresult.txt started from ant works correctly and output is returned to file.
The command cmd.exe /C echo test > C:\testresult.txt started from gradle works correctly and output is returned to file. Great!
The command cmd.exe /C echo test started from ant works correctly and output is returned to stdout. !
The command cmd.exe /C echo test started from gradle works correctly but output is not returned to stdout. !
The command cmd.exe /C mkdir C:\\\\Inetpub\\\\ftproot\\\\temp\\\\jakisnowykatalog started from ant works correctly and directory is created (I need to use \\\\ as path separator because \\, \, / doesn't work)
The command cmd.exe /C mkdir C:\\\\Inetpub\\\\ftproot\\\\temp\\\\jakisnowykatalog started from gradle doesn't work and directory is not created.
I should add that I want to connect with windows ssh server (not unix/mac) but I've also tested those commands with mac shh without success. Please help!
[Another edit]
I've created groovy test code which uses jsch library to execute command and it works. I still don't know why ant task doesn't work.
import com.jcraft.jsch.*
import java.util.Properties;
private void jschTest() {
Session session = null
Channel channel = null
try {
JSch jsch = new JSch()
session = jsch.getSession("host", "login", 22)
session.setPassword("password")
Properties config = new Properties()
config.put("StrictHostKeyChecking", "no")
session.setConfig(config)
session.connect()
String command = "cmd.exe /C mkdir C:\\gradledir"
channel = session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
channel.connect()
}
catch (Exception e) {
println e.getMessage()
}
finally {
if (session!=null) {
session.disconnect()
}
if (channel!=null) {
channel.disconnect()
}
}
}

Assuming you declare a task of type MyCustomTask and execute it correctly, I see no reason why the Ant task wouldn't get executed. The problem is more likely elsewhere (e.g. wrong configuration of the Ant task).

Related

What should i write in jenkins file?

I have an automation project written in Java, using Junit, and I'm trying to create my new Jenkins job pipeline.
I've created the pipeline and a new Jenkins file, but I don't know what this file should contain.
I need to -
build the project
Run the tests by category (I don't want to run
all the test in one job)
Deploy
I've found this one in Jenkins documentation
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building..'
}
}
stage('Test') {
steps {
/* `make check` returns non-zero on test failures,
* using `true` to allow the Pipeline to continue nonetheless
*/
sh 'make check || true'
junit 'pom.xml'
}
}
stage('Deploy') {
steps {
echo 'Deploying....'
}
}
}
}
But I got this message:
"Test reports were found but none of them are new. Did leafNodes run?"
So how do I make it work? and how can I specify an exact category to run?
There are a couple of things you will need to setup first. Like jdk , maven, git credentials. Then your pipeline will looks something like this.
pipeline {
agent {
node {
label 'the label of your agen or have "any" if you didnt specidy one'
}
}
environment {
//maven home as it is configured in Global Configuration
mvnHome = tool 'maven'
}
options{
// remove older builds and artifacts if they exceed 15 builds
buildDiscarder(logRotator(numToKeepStr: '100', artifactNumToKeepStr: '100'))
//add the time stamp to the logs
timestamps()
}
stages {
stage("Git CheckOut") {
steps {
script{
//CheckOut from the repository
def scmVars = checkout([$class: 'GitSCM',
branches: [[name: 'master']], //here you can enter branch name or SHA code
userRemoteConfigs: [[credentialsId: 'credential that you set for you git here',
url: "your git url here"]]])
}
}
}
stage('Build Artifacts') {
steps {
sh "echo Packaging the artifacts!"
//packaging the project
sh "${mvnHome}/bin/mvn clean package "
//archiving the artifacts after the build
sh "echo Archiving the artifacts!"
archiveArtifacts 'target/*.war' // you can deploy to nexus if you setup nexus
}
}
stage('Unit Test') {
steps {
//running the unit tests
sh "${mvnHome}/bin/mvn clean test"
}
}
stage('Transfer war file to Servers') {
steps {
sshagent(['agent name that was setup in your server where you want to deploy artifacts']) {
sh "echo Trasnfering files to servers!"
//copy war file servers
sh 'scp -o StrictHostKeyChecking=no $projPath/target/your war file /your server path'
}
}
}
}
post {
always {
sh "echo Jenkins Job is Done"
}
success {
sh "echo Sending Success Email!"
}
failure {
sh "echo Sending Failed Email!"
}
}
}

Execute a .jar in a Groovy script

I'm creating a test case with Katalon Studio using the script mode which is a groovy script. I need that groovy script to execute a .jar that will be inside the Katalon project folder.
For testing purposes I created a .jar that creates a file named "the-file-name" and prints a message in the console.
I found a way to execute a command in Groovy:
def command = "git --version"
def proc = command.execute()
proc.waitFor()
println proc.in.text
This prints git's version in the Katalon console. So I guessed that putting "java -jar test.jar" would be enough but even though the execution seems to end correctly it also seems that the .jar didn't do anything. Just to be sure, I executed the same .jar using de Windows command line and it works perfectly. The file is created and the message written in the console.
When executing, Katalon console acts as if it was correctly executed. There are no error messages and execution is marked as successful yet the test file "the-file-name" is nowhere to be found and I'm not getting the .jar's console output shown in the Katalon console as in the git command.
Found a way to do it.
public class CustomKeywords {
#Keyword
def runBatch(String path) {
def cmd = "cmd /c \"java -jar \"" + path + "\"\"";
runCmd(cmd)
}
def runCmd(String cmd) {
KeywordUtil.logInfo("cmd: ${cmd}")
def proc = cmd.execute();
def outputStream = new StringBuffer();
def errStream = new StringBuffer()
proc.waitForProcessOutput(outputStream, errStream);
println(outputStream.toString());
println(errStream.toString())
if(proc.exitValue() != 0){
KeywordUtil.markFailed("Out:" + outputStream.toString() + ", Err: " + errStream.toString())
}
}
}

Get output of sh using gradle

I am facing an issue that I'm not able to figure out. What I want to achieve is to have a gradle task that spawn a docker-compose process that is a mssql server, and then use liquibase to run-up all migrations and seed the database.
But the problem is that the docker takes some time to get the server up, and the liquibase is running before it gets up.
What i did was to start docker-compose in a daemon using -d flag, and then use a loop to ping the server until the port 1433 responds and then let the gradle continue with the other dependent tasks (that actually creates the database and seed it).
here is what I did:
task checkDbStatusAndGetsItUp(){
group "localEnvironment"
description "Check current local db is up or sets it up"
dependsOn 'cloneEntityProject'
println 'Checking db Status and setting it up'
println '---------------------------'
def stdoutDocker = new ByteArrayOutputStream()
exec{
executable 'sh'
args "-c", """
docker ps | grep microsoft | wc -c
"""
standardOutput = stdoutDocker
}
doLast {
if (stdoutDocker.toString().trim() == '0') {
exec {
executable 'sh'
workingDir 'setup/dp-entidades'
args "-c", """
docker-compose up -d
"""
}
}
def shouldStop = false;
while (shouldStop == false){
def stdoutPing = new ByteArrayOutputStream()
exec{
workingDir 'setup/dp-entidades'
executable 'sh'
args """
nc -zv localhost 1433
"""
ignoreExitValue = true
standardOutput = stdoutPing
}
println stdoutPing.toString();
sleep(1000)
}
}
}
What I get from the above code is a loop showing that the docker never gets it up. But if I open another terminal and ping it manually it works, and the database is actually up. (I even tried to use telnet, with same results)
What I need to do, to achive the ping from the gradle and if success on conecting to database let the task continue?
-c flag of sh is missing in the last exec block. Another problem is that you never set shouldStop to true, so the last loop will never terminate. You can e.g. check the exit status of exec:
def result = exec { ... }
shouldStop = result.exitValue == 0
Note that you should also limit the number of tries to propagate server failure instead of waiting forever.

error with starting cmd in windows using java?

The following method starts the cmd in Windows and it takes a parameter of the command which need to be run.
I have tested this method using the following commands: net users and it worked fine and it printed the users accounts. but if I run the dir command I get the following error:
java.io.IOEXception:
Cannot run program "dir": CreateProcess error=2, The system cannot find the file specified (in java.lang.ProcessBuilder)
Code :
private String commandOutPut;
public void startCommandLine(String s) throws IOException{
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(s); // you might need the full path
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String commandOutPut;
while ((commandOutPut = br.readLine()) != null) {
this.commandOutPut = this.commandOutPut + "\n" + commandOutPut;
}
System.out.println(this.commandOutPut);
}
Well, obviously, your method does not start cmd. How did you get this notion?
The net command is a standalone command so it runs just fine, but the dir command is not standalone, it is an internal command of cmd.exe, so you cannot run it without launching cmd.exe to execute it.
To get it to work you will have to pass not dir but cmd.exe /c dir or something like that.
Don't know if this perception can help you. But, seems that "net users" are recognized as Windows command, since "Execute" dialog can run it.
But, for some reason, the "dir" command aren't. When try to run, Windows responds that command was not found.
Additionaly, I tried run Command with inline arguments too, but the arguments are simply ignored. (sorry for bad english)
My best guess is that this is because "net" is a real executable (there is a file WINDIR\System32\net.exe"), while "dir" is a builtin command of the command interpreter - it has no executable and is directly executed within cmd.exe.
Howevever you may get around this be invoking "dir" command inside the cmd process. The syntax - as per Microsoft docs - is:
cmd /c dir
There are also some related answers on the site:
How to execute cmd commands via Java
Run cmd commands through java
You can use the following code for this
import java.io.*;
public class demo
{
public static void main(String args[])
{
try
{
Process pro=Runtime.getRuntime().exec("cmd /c dir");
pro.waitFor();
BufferedReader redr=new BufferedReader(
new InputStreamReader(pro.getInputStream())
);
String ln;
while((ln = redr.readLine()) != null)
{
System.out.println(ln);
}
}
catch(Exception e) {}
System.out.println("Done");
}
}

execute multiple commands in cmd using java

I need to execute multiple comments in single cmd window using java.
The comments are
1. cd C:\Apps\wildfly-8.0.0.Final\bin
2. jboss-cli.bat --connect --command=\"deploy --force C:\Users\me\git\test\Test\build\libs\TestEAR.ear
Because I need to execute the second command from the folder "C:\Apps\wildfly-8.0.0.Final\bin".
I tried this :
Runtime.getRuntime().exec("cmd /c start cd C:\\Apps\\wildfly-8.0.0.Final\\bin\\ && start cmd.exe /c jboss-cli.bat --connect --command=\"deploy --force C:\\Users\\me\\git\\test\\Test\\build\\libs\\TestEAR.ear\"");
But it is executing these commands separate , that is it will open one cmd window and executes the first commands , then it will execute the second command in another cmd window , and showing the error :
Could not locate "C:\Users\me\git\test\Test\build\libs\TestEAR.ear".
Please check that you are in the bin directory when running this script.
Press any key to continue . . .
I found some solutions with batch file , but in my application I can't use batch file (must not use batch file ) .
Can anyone suggest a solution ?
If I understand your question you could use a ProcessBuilder and call directory(File). Something like
public static void main(String[] args) throws IOException {
String folder = "C:\\Apps\\wildfly-8.0.0.Final\\bin";
String command = "jboss-cli.bat --connect --command=\"deploy --force "
+ "C:\\Users\\me\\git\\test\\Test\\build\\libs\\TestEAR.ear\"";
ProcessBuilder pb = new ProcessBuilder(command);
pb.directory(new File(folder));
pb.inheritIO();
Process p = pb.start();
try {
p.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Categories