Ausgabe auf dem Bildschirm überschreibende Umleitung

8

Ist es möglich, innerhalb eines Shell-Skripts auf den Bildschirm zu schreiben, während STDOUT und STDERR umgeleitet werden?

Ich habe ein Shell-Skript, das ich STDOUT und STDERR erfassen möchte. Das Skript wird möglicherweise eine Stunde oder länger ausgeführt, daher möchte ich gelegentlich Statusmeldungen auf den Bildschirm schreiben, die angezeigt und nicht umgeleitet (nicht erfasst) werden.

Für ein minimales Beispiel habe ich ein Shell-Skript, sagen wir "./myscript.sh":

#!/bin/sh -u

echo "Message A: This writes to STDOUT or wherever '1>' redirects to."
echo "Message B: This writes to STDOUT or wherever '1>' redirects to.">&1
echo "Message C: This writes to STDERR or wherever '2>' redirects to.">/dev/stderr
echo "Message D: This writes to STDERR or wherever '2>' redirects to.">&2
echo "Message E: Write this to 'screen' regardless of (overriding) redirection." #>???  


Dann möchte ich zum Beispiel diese Ausgabe sehen, wenn ich das Skript wie folgt ausführe:

[~]# ./myscript.sh > fileout 2> filerr
Message E: Write this to 'screen' regardless of (overriding) redirection.
[~]# ./myscript.sh > /dev/null 2>&1
Message E: Write this to 'screen' regardless of (overriding) redirection.
[~]#    


Wenn dies nicht "direkt" möglich ist, ist es möglich, die Umleitung vorübergehend abzubrechen, dann etwas auf den Bildschirm zu drucken und die Umleitung so wiederherzustellen, wie sie war?

Einige Informationen zum Computer:

[~]# uname -srvmpio
Linux 3.2.45 #4 SMP Wed May 15 19:43:53 CDT 2013 x86_64 x86_64 x86_64 GNU/Linux

[~]# ls -l /bin/sh /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root  4 Jul 18 23:18 /bin/sh -> bash
lrwxrwxrwx 1 root root 15 Jun 29  2013 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jun 29  2013 /dev/stdout -> /proc/self/fd/1
Kevin Fegan
quelle
1
echo msg > /dev/tty
Stéphane Chazelas
@strugee - Ich wollte es mit dem Betriebssystem markieren: "GNU / Linux", aber ich durfte nicht (ich habe sogar "GNU-Linux" ausprobiert), also habe ich einzeln als "GNU" und "Linux" getaggt.
Kevin Fegan
@StephaneChazelas - echo msg > /dev/tty. Das hat funktioniert! Ich war mir sicher, dass ich dies früh ohne Erfolg versucht habe, aber ich muss nur andere ähnliche Dinge ausprobiert haben. Auf jeden Fall funktioniert es bei mir. Wenn Sie dies als Antwort angeben möchten, werde ich es als akzeptiert markieren.
Kevin Fegan

Antworten:

4

Versuchen Sie ein Skript wie das folgende:

#!/bin/bash
echo "to fd1" >&1
echo "to fd2" >&2
echo "to screen" >$(tty)

Wenn Sie es nennen, sieht es so aus:

user@host:~# ./script
to fd1
to fd2
to screen
user@host:~# ./script 1>/dev/null
to fd2
to screen
user@host:~# ./script 2>/dev/null
to fd1
to screen
user@host:~# ./script > /dev/null 2>&1
to screen
Chaos
quelle
>/dev/ttyist besser als >$(tty)weil es funktioniert, selbst wenn stdin umgeleitet wird und es nicht durch den Tanz des Scannens gehen muss, /devbis das richtige Gerät gefunden ist.
Celada
2

Ich weiß nicht alles über die Umleitung, aber das ist, was ich tue:

Leiten Sie nicht um, sondern senden Sie die gewünschte Ausgabe als Parameter. Wenn Sie im Skript selbst umleiten, können Sie die Umleitung jederzeit wechseln, indem Sie Folgendes ausführen:

exec 2> /some/new/destination 1> /some/other/destination

aber vielleicht möchten Sie die alten retten ...

exec  3>&1 4>&2 2> /some/new/destination 1> /some/other/destination

Auf diese Weise können Sie darauf zurückkommen ... wenn Sie fertig sind oder auf den Bildschirm schreiben möchten

auf den Bildschirm schreiben: echo "message" 1>&3

oder..

alles erledigt: exec 1>&3 2>&4 # alles geht wieder normal :)

Osirisgothra
quelle
0

Verwenden Sie das Beispiel aus der Antwort von Chaos :

echo "to screen" >$(tty)

hat bei mir nicht funktioniert. Beim Versuch, es zu verwenden, wird eine Fehlermeldung angezeigt:

./myscript.sh: line xx: /dev/pts/3: Permission denied

Ich habe eine Lösung gefunden, um einen anderen Dateideskriptor zu verwenden (9). Hier ist "./myscript.sh":

#!/bin/sh -u

## This is placed one time at the top of the script  
## to detect if file descriptor (9) is available for writing.
if [ ! -t 3 ]; then
    echo "Error, file descriptor (9) not open on terminal." >&2
    echo "" >&2
    if [ ! -t 2 ]; then
        echo "Error, file descriptor (9) not open on terminal."
        echo ""
    fi
    exit 1
fi

echo "Message A: This writes to stdout or wherever '1>' redirects to."
echo "Message B: This writes to stdout or wherever '1>' redirects to.">&1
echo "Message C: This writes to stderr or wherever '2>' redirects to.">/dev/stderr
echo "Message D: This writes to stderr or wherever '2>' redirects to.">&2
echo "Message E: Write this to 'screen' regardless of '1>/2>' redirection." >&9
echo " " >&9

Ich habe den Dateideskriptor verwendet, 9um die "Status" -Nachrichten an auszugeben, aber andere gültige Dateideskriptoren sollten funktionieren.

Um es zu verwenden, müssen Sie beim Aufrufen des Skripts die Umleitung des Dateideskriptors (9) nach STDOUT (9> & 1) als erste Umleitung einschließen.

Hier ist die Ausgabe, wenn ich "./myscript.sh" aufrufe:

[~]# ./myscript.sh
[~]# ./myscript.sh >/dev/null
[~]# ./myscript.sh 2>/dev/null
Error, file descriptor (9) not open on terminal.

[~]# ./myscript.sh >/dev/null 9>&1
Error, file descriptor (9) not open on terminal.

[~]# ./myscript.sh 9>&1 >/dev/null
Message C: This writes to stderr or wherever '2>' redirects to.
Message D: This writes to stderr or wherever '2>' redirects to.
Message E: Write this to 'screen' regardless of '1>/2>' redirection.

[~]# ./myscript.sh 9>&1 2>/dev/null
Message A: This writes to stdout or wherever '1>' redirects to.
Message B: This writes to stdout or wherever '1>' redirects to.
Message E: Write this to 'screen' regardless of '1>/2>' redirection.

[~]# ./myscript.sh 9>&1 >/dev/null 2>&1
[~]# ./myscript.sh 9>&1 &>/dev/null
[~]# ./myscript.sh 9>&1 >&/dev/null
Message E: Write this to 'screen' regardless of '1>/2>' redirection.

[~]#
Kevin Fegan
quelle