Java Runtime.exec("sleep 180 ; ...") - java

I tried to ban an ip-adress temporarly if someone tryes to not join over the proxy to the minecraft server.
String st = e.getRealAddress() + "";
if(!st.startsWith("/x.x.x.x")) {
Runtime runtime = Runtime.getRuntime();
runtime.exec("iptables -A INPUT -s " + st.replace("/","") + " -j DROP");
runtime.exec("sleep 180 ; iptables -D INPUT -s " + st.replace("/","") + " -j DROP");
}
But for some reason to only executes the -A command and after I've waited three minutes I wasn't able to connect. What did I have done wrong?

you can:
decompose yourself the orders in java: iptables , wait, sleep, iptables, ...
then you must wait first iptables to finish:
use waitFor :
Process p = Runtime.getRuntime().exec("your command iptables");
p.waitFor();

Related

grep adds new line if splitted by groovy?

My goal is to get the names of x .conf files in a directory called "conf". My code looks like this:
commandOutput = sshCommand remote: getRemote(), command: getPathCmd(type) + "cd conf; ls | grep '.conf' | grep -Eo '^[a-zA-Z0-9_-]+'"
def instances = commandOutput.split("\n") as String[]
return instances
If i print the variable commandOutput (with two files in the directory) it shows me:
name1
name2
But when i make a for loop to print every slot of the array, i get this:
name1
*empty line*
and
name2
I checked commandOutput[0] with .endsWith("\n") and returned false so i dont know where the new line is coming from.
Is there an obvious reason for that behaviour?
Edit: It also happens here:
command = getPathCmd(type) + getScript(type, "status") + "| grep -Eo '[0-9]{4,5}' | sort -u | grep -v '${params.xyID}\\|" + globalID + "'"
try{
commandOutput = sshCommand remote: getRemote(), command: command
def PIDs = commandOutput.split("\n") as String[]
return PIDs
}
catch(Exception e){
println("XY")
return "XY"
}
Print of commandOutput:
1234
5678
For loop print of PIDs:
1234
*empty line*
and
5678
stringXY = stringXY.replaceAll("[\\\r\\\n]+",""); did the trick. It replaces all new lines.
tr '\n' '\0' as suggested in this thread wouldn't work here, because it would be harder to find out where one name ends and the next one starts.

Using common methods for Jenkins builds

I have multiple Jenkins jobs using pipeline scripts and i use the same method for at least 4 of them
def createJiraLinks(def ticketNumbers) {
ArrayList<String> jiraLinks = new ArrayList<String>();
for(int i =0; i < ticketNumbers.size(); i++) {
def jira_json = sh script: """/usr/local/bin/curl -X GET -H "Content-Type: application/json" --cert-type PEM --key-type PEM -E /Users/Jenkins/.jenkins/workspace/certificates/cert.pem --key /Users/Jenkins/.jenkins/workspace/certificates/cert.pem https://jira.dev.org.co.uk:443/rest/api/2/issue/${ticketNumbers[i]}""", returnStdout: true
def json = jsonParse(jira_json);
def summary = json['fields']['summary'].toString();
jiraLinks.add("[" + ticketNumbers[i] + "](https://jira.dev.org.co.uk/browse/" + ticketNumbers[i] + ")" + " - " + summary);
}
return jiraLinks;
}
How can i have each pipeline job import this method so that if i ever need to update it i can just do it once, the key part here is having the ability to use sh script: as if i run the the curl command using "String.execute()" the command fails as i cannot correctly format it
Any advice/tips appreaciated
Thanks
See the detailed description at Extending with Shared Libraries.

Implement Multi-threading on Java Program

I'm writing a little Java program which uses PsExec.exe from cmd launched using ProcessBuilder to copy and install an application on networked PC (the number of PC that will need to be installed can vary from 5 to 50).
The program works fine if I launched ProcessBuilder for each PC sequentially.
However to speed things up I would like to implement some form of MultiThreading which could allow me to install 5 PC's at the time concurrently (one "batch" of 5 X Processbuilder processes untill all PC's have been installed).
I was thinking of using a Fixed Thread Pool in combination with a Callable interface (each execution of PsExec returns a value which indicates if the execution was succesfull and which I have to evaluate).
The code used for the ProcessBuilder is:
// Start iterating over all PC in the list:
for(String pc : pcList)
{
counter++;
logger.info("Starting the installation of remote pc: " + pc);
updateMessage("Starting the installation of remote pc: " + pc);
int exitVal = 99;
logger.debug("Exit Value set to 99");
try
{
ProcessBuilder pB = new ProcessBuilder();
pB.command("cmd", "/c",
"\""+psExecPath+"\"" + " \\\\" + pc + userName + userPassword + " -c" + " -f" + " -h" + " -n 60 " +
"\""+forumViewerPath+"\"" + " -q "+ forumAddress + remotePath + "-overwrite");
logger.debug(pB.command().toString());
pB.redirectError();
Process p = pB.start();
InputStream stErr = p.getErrorStream();
InputStreamReader esr = new InputStreamReader(stErr);
BufferedReader bre = new BufferedReader(esr);
String line = null;
line = bre.readLine();
while (line != null)
{
if(!line.equals(""))
logger.info(line);
line = bre.readLine();
}
exitVal = p.waitFor();
} catch (IOException ex)
{
logger.info("Exception occurred during installation of PC: \n"+pc+"\n "+ ex);
notInstalledPc.add(pc);
}
if(exitVal != 0)
{
notInstalledPc.add(pc);
ret = exitVal;
updateMessage("");
updateMessage("The remote pc: " + pc + " was not installed");
logger.info("The remote pc: " + pc + " was not installed. The error message returned was: \n"+getError(exitVal) + "\nProcess exit code was: " + exitVal);
}
else
{
updateMessage("");
updateMessage("The remote pc: " + pc + " was succesfully installed");
logger.info("The remote pc: " + pc + " was succesfully installed");
}
Now I've read some info on how to implement Callable and I would like to enclose my ProcessBuilder in a Callable interface and then submit all the Tasks for running in the for loop.
Am I on the right track?
You can surely do that. I suppose you want to use Callable instead of runnable to get the result of your exitVal ?
It doesn't seem like you have any shared data between your threads, so I think you should be fine. Since you even know how many Callables you are going to make you could create a collection of your Callables and then do
List<Future<SomeType>> results = pool.invokeAll(collection)
This would allow for easier handling of your result. Probably the most important thing you need to figure out when deciding on whether or not to use a threadpool is what to do if your program terminates while threads are still running; Do you HAVE to finish what you're doing in the threads, do you need to have seamless handling of errors etc.
Check out java threadpools doc: https://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
or search the web, there are tons of posts/blogs about when or not to use threadpools.
But seems like you're on the right track!
Thank you for your reply! It definitely put me on the right track. I ended up implementing it like this:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5); //NEW
List<Future<List<String>>> resultList = new ArrayList<>();
updateMessage("Starting the installation of all remote pc entered...");
// Start iterating over all PC in the list:
for(String pc : pcList)
{
counter++;
logger.debug("Starting the installation of remote pc: " + pc);
psExe p = new psExe(pc);
Future<List<String>> result = executor.submit(p);//NEW
resultList.add(result);
}
for(Future<List<String>> future : resultList)
{.......
in the last for loop I read the result of my operations and write them on screen or act according to the result returned.
I still have a couple of questions as it is not really clear to me:
1 - If I have 20 PC and submit all the callable threads to the pool in my first For loop, do I get it correctly that only 5 threads will be started (threadpool size = 5) but all will already be created and put in Wait status, and only as soon as the first running Thread is complete and returns a result value the next one will automatically start until all PC are finished?
2 - What is the difference (advantage) of using invokeall() as you suggested compared to the method I used (submit() inside the for loop)?
Thank you once more for your help...I really Love this Java stuff!! ;-)

Appium Server, on windows, is throwing error: Responding to client that we did not find a valid resource

I am trying to run Appium Serve on my Windows 7 machine using a simple command:
D:\Appium\node.exe D:\Appium\node_modules\appium\bin\Appium.js -g C:\Users\vdopia\AppData\Local\Temp\applog_12232015_110310.txt --no-reset
in command prompt, it shows that Appium is started. When I browse the url http://127.0.0.1:4723, I get the message below in my command prompt and because of this I am not able initialize remotedriver also. Surprisingly, the same thing works well in MAC.
Logs:
> info: --> GET / {}
> info: [debug] Responding to client that we did not find a valid resource
> info: <-- GET / 404 0.712 ms - 47
> info: <-- GET /favicon.ico 200 0.535 ms - 1150
I am pasting code here to start appium server, first I am writing command in a sh or bat file then executing the bat file.
public static boolean startAppiumServer()
{
//Kill any Existing Appium Before Starting new session
logger.info("Stopping any running instance of appium. ");
try{SDKCommonUtils.killAppiumServer();}catch(Exception e){}
boolean flag = false;
File logFile = null;
String commandFile = null;
if(System.getProperty("os.name").matches("^Windows.*"))
{
//Getting temp dir
String tempDir = System.getProperty("java.io.tmpdir").toString();
logFile = new File(tempDir+"\\applog"+"_"+MobileTestClass_Methods.DateTimeStamp()+".txt");
commandFile = System.getenv("AUTOMATION_HOME").concat("\\tpt\\appium_commands.bat");
String appiumCmdLocation_Windows = MobileTestClass_Methods.propertyConfigFile.getProperty("appiumCmdLocationForWindows").toString();
String nodeExe = appiumCmdLocation_Windows.concat("\\node.exe");
String appiumJs = appiumCmdLocation_Windows.concat("\\node_modules\\appium\\bin\\Appium.js");
String strText = "start /B " + nodeExe + " " + appiumJs + " -g " + logFile.toString() + " --full-reset --command-timeout 60 ";
FileLib.WriteTextInFile(commandFile, strText);
}
else
{
logFile = new File("/tmp/applog"+"_"+MobileTestClass_Methods.DateTimeStamp()+".txt");
commandFile = System.getenv("AUTOMATION_HOME").concat("/tpt/appium_commands.sh");
String strText = "export PATH=$PATH:/usr/local/bin; /usr/local/bin/appium -g " + logFile.toString() + " --full-reset --command-timeout 60 " ;
FileLib.WriteTextInFile(commandFile, strText);
}
try
{
logger.info("Executing Command File: "+ commandFile +" to start appium service. ");
Runtime.getRuntime().exec(commandFile);
/** wait until appium server is started */
flag = waitForAppiumServer();
}
catch(Exception e)
{
flag = false;
logger.error("There were some issues while executing command to launch appium service. ",e);
}
return flag;
}
If you do not provide server address then it will be used as 0.0.0.0 from command prompt in windows as
info: Appium REST http interface listener started on 0.0.0.0:4723.
Please provide --address 127.0.0.1 --port 4723 parameter from command line and try to use same address and port while initializing driver object in your script.

How to destroy the subprocess of Java Process

I use Runtime.getRuntime().exec to execute command tail -f filename | grep str which is based on OS pipe. I managed to achieve my business logic. But still there is a problem I must solve:
When using pipe, the Process will for another process for tail command:
$ ps -ef | grep test.log
admin 6953 32721 0 16:32 ? 00:00:00 /bin/sh -c tail -f /home/admin
/test.log | unbuffer -p grep '1444379575648'
admin 6957 6953 0 16:32 ? 00:00:00 tail -f /home/admin/test.log
Process.destroy() method destroys itself(pid:6953) only.How can I destroy its subprocess(pid:6957) in my Java program?
Don't use Runtime.getRuntime().exec(...), use 2 ProcessBuilders to explicitly build the individual processes, and connect their inputs and outputs together to do the equivalent of the piping.
Then you will a separate Process object for each, and can kill them as you please.
i found another way:
public static final String getPid() {
try {
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
String name = runtimeBean.getName();
int k = name.indexOf('#');
if (k > 0)
return name.substring(0, k);
} catch (Exception ex) {
}
return null;
}
This works on linux,win,mac.

Categories