B
Beni
Gast
Hallo
Ich muss von Java aus bash in Ubuntu aufrufen. Damit die Environment-Variablen verfügbar sind (das Zeugs das in .bashrc, .profile, etc geladen wird) muss es eine interaktive-login-shell (?) sein.
Jetzt bekomme ich aber immer einen seltsame Fehlermeldung: "bash: no job control in this shell". Danach läuft zwar alles wie es soll, und die "job control" (würde Dinge wie "ctrl+Z" um einen Job zu versenken erlauben) wird auch garnicht benötigt. Aber mich (und mindestens einen Benutzer) stört diese Meldung.
Ich könnte die Meldung einfach in der Anzeige rausfiltern, aber lieber wüsste ich wie ich sie ganz loswerde... Dr. Google konnte mir zwar sagen was die Meldung bedeutet, aber nicht wie ich sie loswerde.
Jede Hilfe ist willkommen
Das Program unten erzeugt das Problem, bei mir ist seine Ausgabe:
[highlight=Java]package tos_spielwiese;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.i
utputStream;
import java.io.PrintWriter;
public class NoJobControl{
public static void main( String[] args ) throws Exception{
ProcessBuilder pb = new ProcessBuilder( "bash", "-l", "-i" );
Process p = pb.start();
StreamGobbler errorGobbler = new StreamGobbler( p.getErrorStream(), System.err );
StreamGobbler outputGobbler = new StreamGobbler( p.getInputStream(), System.out );
errorGobbler.setPartner( outputGobbler );
outputGobbler.setPartner( errorGobbler );
errorGobbler.start();
outputGobbler.start();
PrintWriter writer = new PrintWriter( p.getOutputStream() );
writer.print( "echo kuckuck" );
writer.print( "\n" );
writer.print( "exit" );
writer.print( "\n" );
writer.flush();
int exitValue = p.waitFor();
outputGobbler.join();
errorGobbler.join();
System.out.println( "exit: " + exitValue );
}
/*
*
* Der restliche Code ab hier transferiert lediglich die Ausgabe der
* shell zu System.err/out.
*
*/
/**
* Used to elect a leader when two gobblers try to process their stream
* at the same time. The winner processes its stream first, afterwards
* the looser processes its stream. Leadership can change whenever a
* gobbler blocks.
*/
private static class Leader{
private int time;
public synchronized int time(){
time++;
return time;
}
}
private static class StreamGobbler{
private InputStream input;
private OutputStream output;
boolean usePrintStream = false;
private Running running = new Running();
private Thread thread;
private StreamGobbler partner;
private Leader leader;
public StreamGobbler( InputStream input, OutputStream output ){
this.input = input;
this.output = output;
}
/**
* Sets the partner of this gobble, this gobbler will not process its
* {@link InputStream} at the same time when its partner is reading.
* @param partner the partner
*/
public void setPartner( StreamGobbler partner ){
this.partner = partner;
leader = partner.leader;
if( leader == null ){
leader = new Leader();
}
}
protected void setInput( InputStream input ){
this.input = input;
}
protected void setOutput( OutputStream output ){
this.output = output;
}
public synchronized void start(){
if( thread != null && thread.isInterrupted() )
thread = null;
if( thread == null ){
thread = new Thread( running );
thread.start();
}
}
public synchronized void stop(){
if( thread != null ){
thread.interrupt();
}
}
public void join(){
Thread thread = this.thread;
if( thread != null ){
while( thread.isAlive() ){
try{
thread.join();
}
catch ( InterruptedException e ){
e.printStackTrace();
}
}
}
}
/**
* Called every time when a new byte was transmitted. The default implementation
* does do nothing.
* @param value the byte that was transmitted or -1
*/
protected void piped( int value ){
// nothing
}
/**
* Tells whether this gobble is currently processing input from its
* {@link InputStream}.
* @return <code>true</code> if this gobbler is neither waiting for input
* nor stopped.
*/
public synchronized boolean isReading(){
if( thread == null )
return false;
return running.reading;
}
private class Running implements Runnable{
private volatile boolean reading = true;
private volatile int time = 0;
public void run(){
try {
if( leader != null ){
time = leader.time();
}
while( !Thread.interrupted() ){
int next = 0;
if( input.available() > 0 ){
next = input.read();
}
else{
reading = false;
next = input.read();
if( leader != null ){
time = leader.time();
}
reading = true;
}
if( partner != null ){
while( partner.isReading() && time > partner.running.time ){
Thread.yield();
}
}
if( next == -1 ){
piped( next );
synchronized( StreamGobbler.this ){
thread = null;
}
return;
}
if( output != null ){
output.write( next );
}
piped( next );
}
}
catch( InterruptedIOException ex ){
// ignore
}
catch( IOException ioe ){
ioe.printStackTrace();
}
}
}
}
}
[/highlight]
Ich muss von Java aus bash in Ubuntu aufrufen. Damit die Environment-Variablen verfügbar sind (das Zeugs das in .bashrc, .profile, etc geladen wird) muss es eine interaktive-login-shell (?) sein.
Jetzt bekomme ich aber immer einen seltsame Fehlermeldung: "bash: no job control in this shell". Danach läuft zwar alles wie es soll, und die "job control" (würde Dinge wie "ctrl+Z" um einen Job zu versenken erlauben) wird auch garnicht benötigt. Aber mich (und mindestens einen Benutzer) stört diese Meldung.
Ich könnte die Meldung einfach in der Anzeige rausfiltern, aber lieber wüsste ich wie ich sie ganz loswerde... Dr. Google konnte mir zwar sagen was die Meldung bedeutet, aber nicht wie ich sie loswerde.
Jede Hilfe ist willkommen
Das Program unten erzeugt das Problem, bei mir ist seine Ausgabe:
Code:
bash: no job control in this shell
kuckuck
besigg@pc-10130:~/workspace/TOS Spielwiese$ besigg@pc-10130:~/workspace/TOS Spielwiese$ logout
exit: 0
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.i
import java.io.PrintWriter;
public class NoJobControl{
public static void main( String[] args ) throws Exception{
ProcessBuilder pb = new ProcessBuilder( "bash", "-l", "-i" );
Process p = pb.start();
StreamGobbler errorGobbler = new StreamGobbler( p.getErrorStream(), System.err );
StreamGobbler outputGobbler = new StreamGobbler( p.getInputStream(), System.out );
errorGobbler.setPartner( outputGobbler );
outputGobbler.setPartner( errorGobbler );
errorGobbler.start();
outputGobbler.start();
PrintWriter writer = new PrintWriter( p.getOutputStream() );
writer.print( "echo kuckuck" );
writer.print( "\n" );
writer.print( "exit" );
writer.print( "\n" );
writer.flush();
int exitValue = p.waitFor();
outputGobbler.join();
errorGobbler.join();
System.out.println( "exit: " + exitValue );
}
/*
*
* Der restliche Code ab hier transferiert lediglich die Ausgabe der
* shell zu System.err/out.
*
*/
/**
* Used to elect a leader when two gobblers try to process their stream
* at the same time. The winner processes its stream first, afterwards
* the looser processes its stream. Leadership can change whenever a
* gobbler blocks.
*/
private static class Leader{
private int time;
public synchronized int time(){
time++;
return time;
}
}
private static class StreamGobbler{
private InputStream input;
private OutputStream output;
boolean usePrintStream = false;
private Running running = new Running();
private Thread thread;
private StreamGobbler partner;
private Leader leader;
public StreamGobbler( InputStream input, OutputStream output ){
this.input = input;
this.output = output;
}
/**
* Sets the partner of this gobble, this gobbler will not process its
* {@link InputStream} at the same time when its partner is reading.
* @param partner the partner
*/
public void setPartner( StreamGobbler partner ){
this.partner = partner;
leader = partner.leader;
if( leader == null ){
leader = new Leader();
}
}
protected void setInput( InputStream input ){
this.input = input;
}
protected void setOutput( OutputStream output ){
this.output = output;
}
public synchronized void start(){
if( thread != null && thread.isInterrupted() )
thread = null;
if( thread == null ){
thread = new Thread( running );
thread.start();
}
}
public synchronized void stop(){
if( thread != null ){
thread.interrupt();
}
}
public void join(){
Thread thread = this.thread;
if( thread != null ){
while( thread.isAlive() ){
try{
thread.join();
}
catch ( InterruptedException e ){
e.printStackTrace();
}
}
}
}
/**
* Called every time when a new byte was transmitted. The default implementation
* does do nothing.
* @param value the byte that was transmitted or -1
*/
protected void piped( int value ){
// nothing
}
/**
* Tells whether this gobble is currently processing input from its
* {@link InputStream}.
* @return <code>true</code> if this gobbler is neither waiting for input
* nor stopped.
*/
public synchronized boolean isReading(){
if( thread == null )
return false;
return running.reading;
}
private class Running implements Runnable{
private volatile boolean reading = true;
private volatile int time = 0;
public void run(){
try {
if( leader != null ){
time = leader.time();
}
while( !Thread.interrupted() ){
int next = 0;
if( input.available() > 0 ){
next = input.read();
}
else{
reading = false;
next = input.read();
if( leader != null ){
time = leader.time();
}
reading = true;
}
if( partner != null ){
while( partner.isReading() && time > partner.running.time ){
Thread.yield();
}
}
if( next == -1 ){
piped( next );
synchronized( StreamGobbler.this ){
thread = null;
}
return;
}
if( output != null ){
output.write( next );
}
piped( next );
}
}
catch( InterruptedIOException ex ){
// ignore
}
catch( IOException ioe ){
ioe.printStackTrace();
}
}
}
}
}
[/highlight]