I'm trying to control a game server and display it's output in real time. This is what I have so far:
#!/usr/bin/perl -w
use IO::Socket;
use Net::hostent; # for OO version of gethostbyaddr
$PORT = 9000; # pick something not in use
$server = IO::Socket::INET->new( Proto => 'tcp',
LocalPort => $PORT,
Listen => SOMAXCONN,
Reuse => 1);
die "can't setup server" unless $server;
print "[Server $0 accepting clients]\n";
while ($client = $server->accept()) {
$client->autoflush(1);
print $client "Welcome to $0; type help for command list.\n";
$hostinfo = gethostbyaddr($client->peeraddr);
printf "[Connect from %s]\n", $hostinfo->name || $client->peerhost;
print $client "Command? ";
while ( <$client>) {
next unless /\S/; # blank line
if (/quit|exit/i) {
last; }
elsif (/fail|omg/i) {
printf $client "%s\n", scalar localtime; }
elsif (/start/i ) {
if (my $ping_pid = open(JAVA, "screen java -jar craftbukkit-0.0.1-SNAPSHOT.jar |")) {
while (my $ping_output = <JAVA>) {
# Do something with the output, let's say print
print $client $ping_output;
# Kill the C program based on some arbitrary condition (in this case
# the output of the program itself).
}
}
printf $client "I think it started...\n Say status for output\n"; }
elsif (/stop/i ) {
print RSPS "stop";
close(RSPS);
print $client "Should be closed.\n"; }
elsif (/status/i ) {
$output = RSPS;
print $client $output; }
else {
print $client "FAIL\n";
}
} continue {
print $client "Command? ";
}
close $client;
}
It starts the process just fine, the only flaw is that it's not outputting the output of the Java process to the socket (It is displaying the output in the terminal window that Perl was initiated with) I've tried this with ping and it worked just fine, any ideas?
Thanks in advance!
It sounds like the Java code (or maybe it's screen) is printing some output to the standard error stream. Assuming that you don't want to capture it separately, some easy fixes are:
Suppress it:
open(JAVA, "screen java -jar craftbukkit-0.0.1-SNAPSHOT.jar 2>/dev/null |")
Capture it in the standard output stream:
open(JAVA, "screen java -jar craftbukkit-0.0.1-SNAPSHOT.jar 2>&1 |")
screen redirects the output to the "screen". Get rid of the screen in the command.
Related
I have JDK and I am trying to execute Main.java program which contains infinite loop and I want to break java Main.java < input.txt > output.txt command if it goes into infinite loop and if not infinite loop than dont won't to break program.. Any solution ?? In trouble
<?php
exec('cmd /k c:/wamp/www/javac Main.java 2>&1', $outputAndErrors, $return_value);
for($i=0 ; $i<sizeof($outputAndErrors) ; $i++)
{
$output1=htmlspecialchars($outputAndErrors[$i],ENT_QUOTES);
echo "$output1";
$flag=1;
}
if(!$flag)
{
exec('cmd /k c:/wamp/www/java Main.java < input.txt > output.txt', $outputAndErrors, $return_value);
//want to give timeout but if exec goes to infinite loop than below statement will not executed
}
?>
Try wrapping it in a class like this (essentially wrapping it in nohup COMMAND > /dev/null 2>&1 & echo $! to get the pid and work with it that way in the background)
<?php
// You may use status(), start(), and stop(). notice that start() method gets called automatically one time.
$process = new Process('ls -al');
// or if you got the pid, however here only the status() metod will work.
$process = new Process();
$process.setPid(my_pid);
?>
<?php
// Then you can start/stop/ check status of the job.
$process.stop();
$process.start();
if ($process.status()){
echo "The process is currently running";
}else{
echo "The process is not running.";
}
?>
<?php
/* An easy way to keep in track of external processes.
* Ever wanted to execute a process in php, but you still wanted to have somewhat controll of the process ? Well.. This is a way of doing it.
* #compability: Linux only. (Windows does not work).
* #author: Peec
*/
class Process{
private $pid;
private $command;
public function __construct($cl=false){
if ($cl != false){
$this->command = $cl;
$this->runCom();
}
}
private function runCom(){
$command = 'nohup '.$this->command.' > /dev/null 2>&1 & echo $!';
exec($command ,$op);
$this->pid = (int)$op[0];
}
public function setPid($pid){
$this->pid = $pid;
}
public function getPid(){
return $this->pid;
}
public function status(){
$command = 'ps -p '.$this->pid;
exec($command,$op);
if (!isset($op[1]))return false;
else return true;
}
public function start(){
if ($this->command != '')$this->runCom();
else return true;
}
public function stop(){
$command = 'kill '.$this->pid;
exec($command);
if ($this->status() == false)return true;
else return false;
}
}
?>
This is only a suggestion. There will be better answer for your question.
Inside the java infinity loop check some value from other text file. Its like
while true {
v = readFile('your_txt_file.txt')
if v == "true" {
break;
}
//do your stuff }
If you can set your_txt_file.txt value to false of what ever except true then java loop will be break.
You need to open a port to listen to in java, and then connect and send something to that port from php.
Check out #TomaszNurkiewicz answer here where he says
"""
What you probably want is to create a ServerSocket and listen on it:
ServerSocket serverSocket = new ServerSocket(4000);
Socket socket = serverSocket.accept();
The second line will block until some other piece of software connects to your machine on port 4000. Then you can read from the returned socket. Look at this tutorial, this is actually a very broad topic (threading, protocols...)
"""
and for opening up the socket with php you can use the code (or somethign close to it) provided here by #sanmi from the manual
"""
<?php
error_reporting(E_ALL);
/* Get the port for the WWW service. */
$service_port = getservbyname('www', 'tcp');
/* Get the IP address for the target host. */
$address = gethostbyname('www.example.com');
/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo "socket_create() failed: reason: " .
socket_strerror(socket_last_error()) . "\n";
}
echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result === false) {
echo "socket_connect() failed.\nReason: ($result) " .
socket_strerror(socket_last_error($socket)) . "\n";
}
$in = "HEAD / HTTP/1.1\r\n";
$in .= "Host: www.example.com\r\n";
$in .= "Connection: Close\r\n\r\n";
$out = '';
echo "Sending HTTP HEAD request...";
socket_write($socket, $in, strlen($in));
echo "OK.\n";
echo "Reading response:\n\n";
while ($out = socket_read($socket, 2048)) {
echo $out;
}
socket_close($socket);
?>
"""
In this little perl script using inline saxon XSLT parser:
use Inline::Java;
use warnings;
use XML::Saxon::XSLT2;
open(my $xslt, '<:encoding(UTF-8)', $xslfile) or die $!;
open(my $xml, '<:encoding(UTF-8)', $xmlfile) or die $!;
my $trans = XML::Saxon::XSLT2->new($xslt);
my $output = $trans->transform($xml);
print $output;
I would like to catch the transformation errors from saxon.
Starting the script from the commandline, errors are written to STDERR.
But how can I redirect the error message to a file inside the perl script?
I tried Tie::STDERR which doesn't work.
I tried to redirect STDERR with
open my $log_fh, '>>', '/tmp/the-log-file';
*STDERR = $log_fh;
Then the perl errors are logged in /tmp/the-log-file, but not the saxon errors.
You should be able to do that with Capture::Tiny, which can grab the STDOUT and STDERR from external programs and XS.
use strict;
use warnings;
use XML::Saxon::XSLT2;
use Capture::Tiny 'capture';
my ($xslfile, $xmlfile) = ( ... );
open(my $xslt, '<:encoding(UTF-8)', $xslfile) or die $!;
open(my $xml, '<:encoding(UTF-8)', $xmlfile) or die $!;
my $trans = XML::Saxon::XSLT2->new($xslt);
my $output;
my ( $stdout, $stderr ) = capture {
$output = $trans->transform($xml);
};
print $output;
Please note I did not test this. Also I don't see where you need the Inline::Java.
The JVM has its own notion of standard error that is not easily manipulated from Perl. To do what you want to do I think you have to reset STDERR before the JVM starts up. That will require a BEGIN block that appears before your use Inline Java statement.
Proof of concept:
# javaerr.pl
BEGIN {
open OLDERR, '>&STDERR'; # save orig STDERR
open STDERR, '>', 'foo'; # redirect before JVM starts
}
use Inline Java => <<'END_OF_JAVA_CODE';
public class Foo {
static {
System.err.println("loaded Foo static block");
}
public Foo() {
}
public void warn(String msg) {
System.err.println("Foo warning: " + msg);
}
}
END_OF_JAVA_CODE
*STDERR = *OLDERR; # restore orig STDERR
open STDERR, '>', 'bar'; # or direct it somewhere else
$Foo = Foo->new();
$Foo->warn("hello world");
print STDERR "goodbye\n";
--
$ perl javaerr.pl
$ cat foo
loaded Foo static block
Foo warning: hello world
$ cat bar
goodbye
I've read a lot of questions/examples on this issue, but unfortunately I have not been able to solve my problem. I need to call a Perl script (that I cannot change) from Java code, and then I need to get the output from that script.
The script is used to take student programming homework assignments, and check them for copying by comparing all of them together. The script can take ~45 seconds to run, but only requires the arguments to be properly formatted, there is no interactivity.
My issue is when I call the script from my Java code I get the first line of output from the script but nothing else. I'm using Runtime.exe() and then waitFor() to wait for the script to finish. However the waitFor() function returns before the script actually finishes. I don't know any Perl so I'm not sure if the script is doing something that 'confuses' the java Process object, or if there's an issue in my code.
Process run = Runtime.getRuntime().exec(cmd);
output = new BufferedReader(new InputStreamReader(run.getInputStream()));
run.waitFor();
String temp;
while((temp = output.readLine()) != null){
System.out.println(temp);
}
The Perl script..
use IO::Socket;
#
# As of the date this script was written, the following languages were supported. This script will work with
# languages added later however. Check the moss website for the full list of supported languages.
#
#languages = ("c", "cc", "java", "ml", "pascal", "ada", "lisp", "scheme", "haskell", "fortran", "ascii", "vhdl", "perl", "matlab", "python", "mips", "prolog", "spice", "vb", "csharp", "modula2", "a8086", "javascript", "plsql", "verilog");
$server = 'moss.stanford.edu';
$port = '7690';
$noreq = "Request not sent.";
$usage = "usage: moss [-x] [-l language] [-d] [-b basefile1] ... [-b basefilen] [-m #] [-c \"string\"] file1 file2 file3 ...";
#
# The userid is used to authenticate your queries to the server; don't change it!
#
$userid=[REDACTED];
#
# Process the command line options. This is done in a non-standard
# way to allow multiple -b's.
#
$opt_l = "c"; # default language is c
$opt_m = 10;
$opt_d = 0;
$opt_x = 0;
$opt_c = "";
$opt_n = 250;
$bindex = 0; # this becomes non-zero if we have any base files
while (#ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
($first,$rest) = ($1,$2);
shift(#ARGV);
if ($first eq "d") {
$opt_d = 1;
next;
}
if ($first eq "b") {
if($rest eq '') {
die "No argument for option -b.\n" unless #ARGV;
$rest = shift(#ARGV);
}
$opt_b[$bindex++] = $rest;
next;
}
if ($first eq "l") {
if ($rest eq '') {
die "No argument for option -l.\n" unless #ARGV;
$rest = shift(#ARGV);
}
$opt_l = $rest;
next;
}
if ($first eq "m") {
if($rest eq '') {
die "No argument for option -m.\n" unless #ARGV;
$rest = shift(#ARGV);
}
$opt_m = $rest;
next;
}
if ($first eq "c") {
if($rest eq '') {
die "No argument for option -c.\n" unless #ARGV;
$rest = shift(#ARGV);
}
$opt_c = $rest;
next;
}
if ($first eq "n") {
if($rest eq '') {
die "No argument for option -n.\n" unless #ARGV;
$rest = shift(#ARGV);
}
$opt_n = $rest;
next;
}
if ($first eq "x") {
$opt_x = 1;
next;
}
#
# Override the name of the server. This is used for testing this script.
#
if ($first eq "s") {
$server = shift(#ARGV);
next;
}
#
# Override the port. This is used for testing this script.
#
if ($first eq "p") {
$port = shift(#ARGV);
next;
}
die "Unrecognized option -$first. $usage\n";
}
#
# Check a bunch of things first to ensure that the
# script will be able to run to completion.
#
#
# Make sure all the argument files exist and are readable.
#
print "Checking files . . . \n";
$i = 0;
while($i < $bindex)
{
die "Base file $opt_b[$i] does not exist. $noreq\n" unless -e "$opt_b[$i]";
die "Base file $opt_b[$i] is not readable. $noreq\n" unless -r "$opt_b[$i]";
die "Base file $opt_b is not a text file. $noreq\n" unless -T "$opt_b[$i]";
$i++;
}
foreach $file (#ARGV)
{
die "File $file does not exist. $noreq\n" unless -e "$file";
die "File $file is not readable. $noreq\n" unless -r "$file";
die "File $file is not a text file. $noreq\n" unless -T "$file";
}
if ("#ARGV" eq '') {
die "No files submitted.\n $usage";
}
print "OK\n";
#
# Now the real processing begins.
#
$sock = new IO::Socket::INET (
PeerAddr => $server,
PeerPort => $port,
Proto => 'tcp',
);
die "Could not connect to server $server: $!\n" unless $sock;
$sock->autoflush(1);
sub read_from_server {
$msg = <$sock>;
print $msg;
}
sub upload_file {
local ($file, $id, $lang) = #_;
#
# The stat function does not seem to give correct filesizes on windows, so
# we compute the size here via brute force.
#
open(F,$file);
$size = 0;
while (<F>) {
$size += length($_);
}
close(F);
print "Uploading $file ...";
open(F,$file);
$file =~s/\s/\_/g; # replace blanks in filename with underscores
print $sock "file $id $lang $size $file\n";
while (<F>) {
print $sock $_;
}
close(F);
print "done.\n";
}
print $sock "moss $userid\n"; # authenticate user
print $sock "directory $opt_d\n";
print $sock "X $opt_x\n";
print $sock "maxmatches $opt_m\n";
print $sock "show $opt_n\n";
#
# confirm that we have a supported languages
#
print $sock "language $opt_l\n";
$msg = <$sock>;
chop($msg);
if ($msg eq "no") {
print $sock "end\n";
die "Unrecognized language $opt_l.";
}
# upload any base files
$i = 0;
while($i < $bindex) {
&upload_file($opt_b[$i++],0,$opt_l);
}
$setid = 1;
foreach $file (#ARGV) {
&upload_file($file,$setid++,$opt_l);
}
print $sock "query 0 $opt_c\n";
print "Query submitted. Waiting for the server's response.\n";
&read_from_server();
print $sock "end\n";
close($sock);
Thank you for any input you may have on my problem.
You can use my native Java client for MOSS instead .
Don't mind the version number. I've been using it in production successfully.
I need to write a Perl script that pipes input into a Java program. This is related to this, but that didn't help me. My issue is that the Java app doesn't get the print statements until I close the handle. What I found online was that $| needs to be set to something greater than 0, in which case newline characters will flush the buffer. This still doesn't work.
This is the script:
#! /usr/bin/perl -w
use strict;
use File::Basename;
$|=1;
open(TP, "| java -jar test.jar") or die "fail";
sleep(2);
print TP "this is test 1\n";
print TP "this is test 2\n";
print "tests printed, waiting 5s\n";
sleep(5);
print "wait over. closing handle...\n";
close TP;
print "closed.\n";
print "sleeping for 5s...\n";
sleep(5);
print "script finished!\n";
exit
And here is a sample Java app:
import java.util.Scanner;
public class test{
public static void main( String[] args ){
Scanner sc = new Scanner( System.in );
int crashcount = 0;
while( true ){
try{
String input = sc.nextLine();
System.out.println( ":: INPUT: " + input );
if( "bananas".equals(input) ){
break;
}
} catch( Exception e ){
System.out.println( ":: EXCEPTION: " + e.toString() );
crashcount++;
if( crashcount == 5 ){
System.out.println( ":: Looks like stdin is broke" );
break;
}
}
}
System.out.println( ":: IT'S OVER!" );
return;
}
}
The Java app should respond to receiving the test prints immediately, but it doesn't until the close statement in the Perl script. What am I doing wrong?
Note: the fix can only be in the Perl script. The Java app can't be changed. Also, File::Basename is there because I'm using it in the real script.
I've grown rather fond of the IO::Handle derived modules. They make it easy to control flushing, reading data, binary mode, and many other aspects of a handle.
In this case we use IO::File.
use IO::File;
my $tp = IO::File->new( "| java -jar test.jar" )
or die "fail - $!";
# Manual print and flush
$tp->print( 'I am fond of cake' );
$tp->flush;
# print and flush in one method
$tp->printflush( 'I like pie' );
# Set autoflush ON
$tp->autoflush(1);
$tp->print( 'I still like pie' );
Also, since the file handle is lexically scoped, you don't have to close it manually. It will automatically close when it goes out of scope.
BTW, unless you are targeting a perl older than 5.6, you can use the warnings pragma instead of -w. See perllexwarn for more info.
$|=1 only works on the currently selected file handle (by default, STDOUT). To make your TP file handle hot you need to do this after opening it:
select(TP);
$| = 1;
select(STDOUT);
I'd like to test which of two implementation in java of a problem is the fastest.
I've 2 jar files with the two implementation I can execute from the terminal. I want to execute both about 100 times and analyse which one is the fastest to do that or that task.
In the output one of the line is "executing time : xx", I need to catch this xx to put in an array or something like that to analyse it later
While I'm executing the jar, I've also to give some input commands (like a name to search or a number).
I don't with which language is it the easiest to do it.
I know the basis in Bash and Python
thank you
Excuse me, but Why you dont make a jar that call n-times any jar?
For Example:
public static void main(String[] args) {
for(int i=0;i<1000;i++) {
params1 = randomNumber();
params2 = randomName();
...
paramsN = randomTime();
MYJAR1 test1 = new MYJAR1(params1,params2,...,paramsN);
timerStart();
test1.start();
timerEnd();
printTimer();
}
}
and make the same for the second jar.
I hope that my idea can help you.
Bye
If you use (say) Perl, you can spawn the process off, capture the output via a redirection and filter the times. e.g.
if (open(PROCESS, "myproc |")) {
while(<PROCESS>) {
if (/executing time : (\d+)/) {
# $1 has the time now
}
}
}
(not compiled or tested!)
Perhaps the simplest way of analysing the data is to redirect the above output to a file, and then load it into Excel. You can then use Excel to calculate averages/max/mins and std. devs (if you wish) trivially.
Ok I've found with 3 different scripts ^^
in the java code, for each function :
long time1 = System.currentTimeMillis();
// some code for function 1
long time2 = System.currentTimeMillis();
try {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(new File("log.txt"),true));
osw.write("function1,"+(time2 - time1)+"\n");
osw.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
a bash code to run the 500 times the two algorithms
#!/bin/bash
i=0
while [ $i -lt 500 ]
do
./algo1.ex
./algo2.ex
i=$(( $i+1 ))
done
an (or two actually, one for each algorithm) expect code to do the command during the execution
#!/usr/bin/expect -f
spawn java -jar algo1.jar
expect "enter your choice" {send "1\n"}
expect "enter a name :" {send "Peju, M.\n"}
expect "enter your choice" {send "2\n"}
expect "enter a name :" {send "Creasy, R. J.\n"}
expect "enter your choice" {send "0\n"}
exit
As I didn't know how to do it in bash, to count I used a python code
#!/usr/bin/python
# -*- coding: utf8 -*-
import sys
if __name__ == "__main__":
if sys.argv[1:]:
arg = sys.argv[1]
filin = open(arg, 'r')
line = filin.readline()
res= 0, 0, 0
int n = 1
while line !='':
t = line.partition(',')
if t[0] == "function1":
res = (res[0] + int(t[2]), res[1], res[2])
if t[0] == "function2":
res = (res[0], res[1] + int(t[2]), res[2])
if t[0] == "function3":
res = (res[0], res[1], res[2] + int(t[2]))
ligne = filin.readline()
n = n+1
print res
print (res[0]/(n/3.0), res[1]/(n/3.0), res[2]/(n/3.0))
filin.close()
and it works
but thanks for your propositions