2009-03-11 13 views
4

Ich will meine KSH-Skript unterschiedliches Verhalten in Abhängigkeit davon haben, ob es ist etwas eingehender durch stdin oder nicht:ksh: wie stdin zu testen?

(1) cat file.txt | ./script.ksh (then do "cat <&0 >./tmp.dat" and process tmp.dat) 
vs. (2) ./script.ksh (then process $1 which must be a readable regular file) 

für stdin prüfen, um zu sehen, ob es ein Terminal [-t 0] ist nicht hilfreich, weil Mein Skript wird von einem anderen Skript aufgerufen.

Doing "Katze < & 0> ./ tmp.dat" zu überprüfen, tmp.dat Größe hängt auf einen EOF von Stdin warten, wenn Stdin "leer" ist (2. Fall).

Wie überprüft man einfach, ob stdin "leer" ist oder nicht ?!

+0

was ist mit Überprüfung der Länge der Argumente? ($ #) Wenn es ein $ 1 gibt, dann schließen Sie daraus eine Lesung ab. Wenn nicht, lesen Sie von stdin ich würde sagen. –

+0

Wenn ich nur könnte! Verwendung: ./script.ksh <-d dest> [-f from_sys] [Datei, Datei1, ..]. Wenn stdin => [file, file1, ..] nicht verarbeitet werden soll, einfach verschoben. Wenn keine stdin => Prozessdatei, verschiebe file1, .. Wenn keine stdin, noch [Datei, Datei1, ..] => Fehler: Benutzer muss einige zur Verarbeitung bereitstellen! –

+0

ExpertNoob, möchten Sie diese Frage möglicherweise als beantwortet markieren. :) – vladr

Antwort

3

EDIT: Sie sind auf HP-UX läuft

Getestet [ -t 0 ] auf HP-UX und es scheint, für mich zu arbeiten.

/tmp/x.ksh:

#!/bin/ksh 
/tmp/y.ksh 

/tmp/y.ksh:

#!/bin/ksh 
test -t 0 && echo "terminal!" 

Lauf /tmp/x.ksh druckt: Ich habe das folgende Setup verwendet terminal!

Könnten Sie die oben auf Ihrer Plattform bestätigen und/oder bieten eine alternativer Testaufbau, der Ihre Situation besser widerspiegelt? Wird Ihr Skript letztendlich von cron erzeugt?


EDIT 2

Wenn verzweifelt, und wenn Perl verfügbar ist, definieren:

stdin_ready() { 
    TIMEOUT=$1; shift 
    perl -e ' 
    my $rin = ""; 
    vec($rin,fileno(STDIN),1) = 1; 
    select($rout=$rin, undef, undef, '$TIMEOUT') < 1 && exit 1; 
    ' 
} 

stdin_ready 1 || 'stdin not ready in 1 second, assuming terminal' 

EDIT 3

Bitte beachten Sie, dass das Timeout kann müssen signifikant sein Wenn Ihre Eingabe von sort, ssh usw. kommt (all diese Programme können die Pipe mit Ihrem Skript in Sekunden oder Minuten erzeugen und herstellen, bevor Sie irgendwelche Daten darüber erzeugen). Auch die Verwendung eines hohen Timeouts kann Ihr Skript dramatisch benachteiligen, wenn nichts läuft die Eingabe für den Anfang (z. B.

Wenn möglicherweise große Timeouts ein Problem darstellen und Sie die Art und Weise beeinflussen können, in der Ihr Skript aufgerufen wird, dann sollten Sie die Aufrufer dazu zwingen, Ihr Programm explizit anzugeben, ob stdin verwendet werden soll benutzerdefinierte Option oder in der Standard GNU oder tar Art und Weise (zB Skript [Optionen [-]] FILE ..., wobei Datei ein Dateiname sein kann, eine - Standardeingabe oder eine Kombination daraus, und Ihr Skript würde nur Lesen Sie von der Standardeingabe, wenn - als Parameter übergeben wurden.)

+0

Ich bin auf HP-UX :-( Gibt es ein Mittel zur Anzeige bestehender Rohre unter HP-UX? –

+0

Hmmm, doch 'test-t 0' identifiziert korrekt die fd als ein Terminal auf meinem hpux, auch wenn der Test wird in einem Skript ausgeführt, das von einem anderen Skript aufgerufen wird (HP-UX HP-A500 B.11.11 U 9000/800 538790518 unbegrenzte Benutzerlizenz) – vladr

+0

Nun, Test -t 0 funktioniert auch in meinen Tests, aber mein Skript wird aufgerufen durch einige andere, einige müssen schwarze Magie mit Dateideskriptoren tun .. Mein Skript ist es, eine bestehende auf vielen Servern weltweit zu ersetzen, so muss es kugelsicher sein.Ihre Perl-Lösung ist großartig, ich teste es jetzt. Danke! –

0

Warum nicht auf eine traditionellere Weise lösen, und das Befehlszeilenargument verwenden, um anzugeben, dass die Daten von stdin kommen werden?

Für ein Beispiel betrachte man den Unterschied zwischen:

echo foo | cat -

und

echo foo > /tmp/test.txt

cat /tmp/test.txt

2

Diese Strategie für bash arbeitet, und würde für KSH wahrscheinlich arbeiten. Poll 'tty':

#!/bin/bash 
set -a 

if [ "$(tty)" == 'not a tty' ] 
then 
    STDIN_DATA_PRESENT=1 
else 
    STDIN_DATA_PRESENT=0 
fi 

if [ ${STDIN_DATA_PRESENT} -eq 1 ] 
then 
    echo "Input was found." 
else 
    echo "Input was not found." 
fi 
+0

Funktioniert auch mit ksh. – Boune

+2

Bitte beachten Sie, dass Sie auf nicht-englischen Systemen die lokalisierte Version von "not a tty" erhalten. Eine Möglichkeit, dies zu vermeiden, ist das Hinzufügen der Zeile "LANG = C" am Anfang des Skripts. – chiborg