Woran erkenne ich das ein befehl funktioniert hat

N

Nano

Foren As
Hallo zusammen, ich schreibe in c ein programm das eine shell als kind hat dieser befehle über pipes sendet, die shell sie ausführt und per pipe daten zurückgibt ich hab nun folgendes problem bei dem ganzen, mein vaterprozess der die daten an die shell gibt und von ihr empfängt wird per select so lange schlafen geschickt bis auf der von der shell ausgenden pipe ( stdout ) daten kommen, das funktioniert bei allen befehlen mit rückgabe wie z.b ls , cat etc ohne problem, allerdings weiss ich woran ich sehe ob z.b. ein befehl wie mkdir "fertig" ist da er ja im erfolgsfall keine rückgabe liefert und so meine pipe auch keine daten bekommt folglich der prozess weiter schläft.

Es handelt sich zwar um ein C programm denke aber das diese frage eher hier rein passt.

Nochmal um es etwas vereinfacht darzustellen

Prozess 1 schickt über pipes einen befehl an Prozess 2 ( hier läuft eine Shell )
Prozess 1 geht schlafen bis Daten von P2 kommen ( per select gelöst )
Prozess 2 arbeitet befehl ab, daten von stdout werden über die pipe an P1 gesendet

Problem : P2 erhält befehl der keine rückgabe über stdout liefert.
Wie z.b chmod oder mkdir etc...

Wie kann ich abfragen ob das geschehen ist ?
 
tomekk@gentoo ~ $ mkdir -v test
mkdir: Verzeichnis »test« angelegt
tomekk@gentoo ~ $
Gut 99% der Befehle haben den Verbose mode.

Edit> Was hast du eigentlich vor? Eine Shell in einer Shell zu programmieren? Oo
 
Wenn du in der Shell einen Programm startest, kannst du mit echo $? den Rückgabewert abfragen.
Wenn du in der Shell ein Programm ausführst, wird zuerst ein Kind erzeugt. Das könnte dir evtl. auch weiter helfen.
 
Gut 99% der Befehle haben den Verbose mode.

Edit> Was hast du eigentlich vor? Eine Shell in einer Shell zu programmieren? Oo

danke aber das hilft an der stelle nicht da ich den befehl nicht ändern will der eingegeben wird.

ich schreibe ein frontend für kommandozeilenorientierte programme, die shell war hier nur ein beispiel, sinn des ganzen ist es für programm die keine history funktion ( wie in bash ) eben dies zu bieten.
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Wenn du in der Shell einen Programm startest, kannst du mit echo $? den Rückgabewert abfragen.
Wenn du in der Shell ein Programm ausführst, wird zuerst ein Kind erzeugt. Das könnte dir evtl. auch weiter helfen.

$? ist mir bekannt wobei diesen zu erfragen bei der shell ein problem darstellt, weil der prozess1 ja solange schläft bis er daten erhält und das programm auch nicht ausschließlich für die shell gedacht ist sondern auch für andere kommandozeilen orientierte programme.
 
Zuletzt bearbeitet:
Also nochmal, was willst du genau machen? :D

Eine Historyfunktion für was? Für mkdir z.b oder wie?

Beschreib mal genau was du vor hast.
 
ich möchte ein frontend für kommandozeilenorientierte programme schrieben, dazu kommen logfiles über ein und ausgabe etc.

So hätte man z.b für programme wie sqlplus oder die normale shell eine kommandohistory wie in der bash...

das hab ich soweit auch alles fertig implementiert, mein problem liegt in befehlen die keinen output erzeugen, da ich im parent prozess auf die rückgabe der daten warte.

Ich suche also eine möglichkeit festzustellen ob in einem laufenden "programm" wie z.b einer shell oder sqlplus die ich in einem gesonderten prozess starte, der befehl ausgeführt worde
Code:
//P2
{
        // umleitungen per pipes
        //stdout P1 = stdin P2
        // stdout P2 = stdin P1

        ......

    if(execl("/bin/sh","sh",NULL) == -1){
            fprintf(stderr,"execl Error!");
            exit(1);
        }
}

z.z habe ich es so gelöst das ich im 2ten prozess daten eingaben lese sie an den prozess weiterleite den aktuellen mit select verzögere bis ich die antwort des 2ten prozesses ( siehe code beispiel ) erhalte. Das funkioniert allerdings nur bei befehlen die auch einen output erzeugen, meine frage :

Wie mache ich das :
a)bei Befehlen die keinen Output erzeugen
b) nicht shell spezifisch es könnte auch z.b sqlolus im prozess laufen
c) ohne das der prozess in dem die shell oder was auch immer läuft beendet wird
 
Vielleicht wirst du dich schon gefrag haben wieso es in c immer "INT main(.." ist und nicht "void main(.." ist, das liegt daran das dir Programme auch rückgabewerte zurückgeben.

Das könntest du ausprobieren mit "ls dum || echo fail && echo ok"

Ich bin mir zwar nicht sicher was genau execl ausgibt, aber mit system() hast du vielleicht etwas mehr spaß.

Hier die return values zu system()
RETURN VALUE
The value returned is -1 on error (e.g. fork(2) failed), and the
return status of the command otherwise
. This latter return status is
...
 
Vielleicht wirst du dich schon gefrag haben wieso es in c immer "INT main(.." ist und nicht "void main(.." ist, das liegt daran das dir Programme auch rückgabewerte zurückgeben.

Das könntest du ausprobieren mit "ls dum || echo fail && echo ok"

Ich bin mir zwar nicht sicher was genau execl ausgibt, aber mit system() hast du vielleicht etwas mehr spaß.

Hier die return values zu system()

die übergabe der parameter beim programmstart ist ja in diesem fall völlig egal da die shell bzw das programm was auch immer im prozess x gestartet wird erst zur laufzeit entsteht.

Aber danke für den hinweis auf system mir war nicht klar das es den befehlsstatus zurückgibt, werd gleich mal versuche das dem entsprechend zu ändern.
 
echo $?

>>0 --> befehl wurde erfolgreich ausgeführt

>>1 --> befehl hatte einen fehler
 
<klugshice>
Code:
ls dum || echo fail && echo ok
ist falsch. Das muss
Code:
ls dum && echo success || echo fail
heißen.
</klugshice>
 
Wenn du bei execl() an die Shell die Option "-i" mit übergibst, wird diese in den interaktiven Modues gesetzt. Dann liefert sie (vermutlich auf stderr) einen Prompt (je nach Zusammenhang PS1, PS2 oder PS3), den dein Programm einfach erkennen kann.

Genau so kannst du z.B. bei sqlplus auf die verschiedenen Prompts ("SQL>", danach Zeilennummern "2", "3", ... bis das Statement komplett eingegeben ist) warten (die kommen allerdings auf stdout).

Für jedes Programm, das du so steuern willst, musst du also rausbekommen, was für Prompts es schickt, und auf welchem Weg.

Grüsse

NB: Evtl. wäre es eine Überlegung wert, die Kommunikation zwischen deinem Master- und Slave-Prozess über Pseudo-TTYs (siehe pty(7)) abzuwickeln statt über Pipes; dann bekämen interaktive Programme - wie die Shell - eine "normale" Umgebung statt einer Simulation mit Pipes, die sich ja doch deutlich anders verhalten als Terminals ;-)
 
echo $?

>>0 --> befehl wurde erfolgreich ausgeführt

>>1 --> befehl hatte einen fehler

die shell war ein beispiel es kann auch z.b sqlplus sein womit diese lösung leider nicht allg. funktioniert...
wäre es nur die shell könnte ich auch einfach (befehl ; echo " ") übergeben und mit select warten
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Wenn du bei execl() an die Shell die Option "-i" mit übergibst, wird diese in den interaktiven Modues gesetzt. Dann liefert sie (vermutlich auf stderr) einen Prompt (je nach Zusammenhang PS1, PS2 oder PS3), den dein Programm einfach erkennen kann.

Genau so kannst du z.B. bei sqlplus auf die verschiedenen Prompts ("SQL>", danach Zeilennummern "2", "3", ... bis das Statement komplett eingegeben ist) warten (die kommen allerdings auf stdout).

Für jedes Programm, das du so steuern willst, musst du also rausbekommen, was für Prompts es schickt, und auf welchem Weg.

Grüsse

NB: Evtl. wäre es eine Überlegung wert, die Kommunikation zwischen deinem Master- und Slave-Prozess über Pseudo-TTYs (siehe pty(7)) abzuwickeln statt über Pipes; dann bekämen interaktive Programme - wie die Shell - eine "normale" Umgebung statt einer Simulation mit Pipes, die sich ja doch deutlich anders verhalten als Terminals ;-)

danke für den tip ich werde mit pty gleich anschauen,
was die lösung mit dem promptzeichen betrifft wäre diese leider nicht allg. lösbar
 
Zuletzt bearbeitet:
Hi Nano,

du hast natürlich recht, eine "allgemeine" Lösung gibt es nicht. Eventuell ist das aber auch gar nicht wirklich nötig, dein Programm muss ja nicht intelligenter sein, als der, der vor der Tastatur sitzt, und der das Master-Programm kontrolliert.

Was macht der User, wenn er einige Zeit lang nichts sieht? Er drückt irgendwelche Knöpfe ...

Also: dein Programm kann entweder versuchen ebenso schlau zu sein, und nach einem (konfigurierbaren) Timeout irgendwelche sinnfreien/konfigurierbaren Eingaben (RETURN, SPACE, Control-L, ...) an das Slave-Programm zu schicken ... oder du überwachst mit select() einfach gleichzeitig sowohl die Tastatur, über die dein Master-Programm die Benutzereingaben erhält, und die Pipes, über die es stdout und stderr (und ggf. weitere Kanäle) vom Slave zurückbekommt, und überlässt es vollkommen dem Anwender, zu reagieren oder eben nicht ...

Grüsse
 
danke floyd , das problem bei der sache ist nur das es so durchaus vorkommen kann das ein befehl länger dauert simples beispiel (sleep 10 ; wasauchimmer) , wenn der user jetzt nach sagne wir einem timeout von 5 sekunden wieder befehle eingeben kann bekommt er mitten in seine eingabe die antwort des anderen prozesses
 
Consider:
Code:
#!/usr/bin/env perl
use strict;
use warnings;
use Term::ReadLine;

my $term = Term::ReadLine->new('foo');

while (my $line = $term->readline('$ ')) {
    print "got: $line\n";
}
Wie könnte man diesem Script Eingaben übergeben? (Versuch macht kluch.)
Ich würde schätzen dazu braucht man libexpect oder so.
 
Hi Nano,

ich denke ja auch, dass der zweite Ansatz - die Steuerung (und damit die Verantwortung) komplett dem Benutzer zu überlassen - besser ist. Und die Vermischung von Ein- und Ausgaben sollte kein Problem darstellen; das passiert ja auch, wenn du direkt z.B. in der Shell arbeitest: du kannst ohne Weiteres schon neue Kommandos eingeben, während noch die Ausgabe von den vorherigen kommt ...
 
die shell war ein beispiel es kann auch z.b sqlplus sein womit diese lösung leider nicht allg. funktioniert...
wäre es nur die shell könnte ich auch einfach (befehl ; echo " ") übergeben und mit select warten
.
.
.
EDIT (autom. Beitragszusammenführung) :
.



danke für den tip ich werde mit pty gleich anschauen,
was die lösung mit dem promptzeichen betrifft wäre diese leider nicht allg. lösbar

verstehe nicht, was du dmir eigentlöich sagen willst. es geht doch um shellscripte oder nicht?
 
verstehe nicht, was du dmir eigentlöich sagen willst. es geht doch um shellscripte oder nicht?

nein um ein c programm siehe erster post ;)

ich hab das programm jetzt entsprechend floyds vorschlag geändert, select bekommt ein timeout und ist auch durch usereingabe beendbar, das ist wohl der einzige weg?!
 
dann ist es falsch hier: Unixboard.de--> Programmieren unter Linux/Unix--> Shell-Skripte--> Woran erkenne ich das ein befehl funktioniert hat
 
hab ich ja im thread geschrieben, wobei die sprache hier realtiv egal ist , die frage wahl darauf bezogen ob man an den return 0 irgendeier funktion ein singal knüpfen kann wenn man die funktion selbst nicht ändern kann, und das würde ich eher hier einordnen
 

Ähnliche Themen

Nachrichtendienst ("WinPopup") via smbclient funktioniert nach Upgrade nicht mehr.

Auf eine prozess Warten

C: Umschalten bei ständig laufendem Cildprocess

Pipefehler unter Solaris 10 X86

Samba Update von 3.2.5 auf 3.5.6 - Probleme beim Server Browsen

Zurück
Oben