Je voudrais faire en sorte qu'un script bash produise des informations supplémentaires aux descripteurs de fichiers (FD) supérieurs ou égaux à 3, lorsqu'ils sont ouverts. Pour tester si un FD est ouvert, j'ai imaginé l'astuce suivante:
if (printf '' 1>&3) 2>&-; then
# File descriptor 3 is open
else
# File descriptor 3 is not open
fi
C'est suffisant pour mes besoins, mais je suis curieux de savoir s'il existe un moyen plus idiomatique de tester si un FD est valide. Je suis particulièrement intéressé à savoir s'il existe un mappage de l' fcntl(1)
appel système à une commande shell, qui permettrait la récupération des drapeaux FD ( O_WRONLY
et O_RDWR
pour tester si le FD est accessible en écriture et O_RDONLY
et O_RDWR
pour tester si le FD est lisible).
la source
<>
? Le shell ne va pas lire depuis son stderr, pourquoi voudriez-vous l'ouvrir en lecture + écriture? Que voulez-vous dire par ce qui est arrivé à intrinsèque? ?Dans la description de l' utilisation de l'application POSIX, vous trouverez les éléments suivants:
command
C'est pourquoi vous pouvez simplement faire:
Ou...
Qui écrira une chaîne suivie d'une ligne
\n
électronique soit sur stdout soit sur 3 et transmettra toujours un état de sortie non nul lorsque 3 n'est pas ouvert car les calculs effectués à la$?
fin échouent à convertir l'octal 08 en % décimal mais tronqué à rien du tout l'octal 00 .Ou...
Mais si vous utilisez
ksh93
, vous pouvez simplement faire:Pour une liste des descripteurs de fichiers ouverts. Ajoutez
-l
pour voir où ils vont.la source
Les descripteurs de fichiers ouverts se trouvent dans
/proc/<pid>/fd
. Pour répertorier, par exemple, les descripteurs de fichiers ouverts du shell actuel, vous pouvez émettrels -l /proc/$$/fd
qui devrait vous donner quelque chose comme:Lorsque vous ouvrez un fichier à l'aide de:
Il doit être répertorié par un nouveau
ls -l /proc/$$/fd
:Si vous fermez à nouveau le descripteur de fichier à l'aide,
exec 7>&-
il n'est plus répertorié dans/proc/$$/fd
.la source
pfiles <pid>
pour voir quel descripteur de fichier est connecté à quel fichier tout enls -l
affichant la connexion sous Linux.[ -e /proc/$$/fd/3 ]
, mais je préfère ne pas me fier à procfs, car il est déprécié dans FreeBSD et peut-être aussi dans d'autres unités.pfiles <pid>
oulsof -p <pid>
à voir quels descripteurs de fichiers sont ouverts./proc
n'existe pas du tout sur OpenBSD. Sur FreeBSD et NetBSD, il doit êtremount
explicitement supprimé et/proc/<PID>
ne pas avoir de sous-répertoirefd
.Votre astuce est mignonne; mais pour une manière idiomatique, je me demande pourquoi vous n'avez pas utilisé:
la source
{ true >&3; } 2> /dev/null
pour éviter la fourche. Ou{ command exec >&3; } 2> /dev/null
si vous souhaitez rediriger stdout vers celui-ci.{ true >&3; } 2> /dev/null
n'affectera pas l'environnement actuel non plus et ne se bifurquera pas (sauf dans le shell Bourne). Je veux dire que(exec 1>&3) 2>&-
cela retournera vrai pour un fd ouvert en mode lecture seule.exec
être une fonction intégrée spéciale quittera le shell en cas d'échec (pour bash, uniquement en mode de conformité POSIX).command exec
empêche cela.true
n'est pas une fonction spéciale. Notez celaexec
etcommand exec
affectez l'environnement actuel (c'est pourquoi j'ai dit si vous voulez rediriger stdout vers lui ).Si vous êtes intéressé par une solution à faible fourche afin de l'utiliser de manière répétée, je suggère cette fonction:
Et voici ce qu'il produit avec un
zsh
:la source
exec >&3
tuera l'obus lorsque 3 n'est pas ouvert.zsh
etbash
. Pourriez-vous fournir le shell sur lequel l'échec aexec
provoqué unexit
?bash
faireset -o posix
et réessayer. Danszsh
... je pense qu'il s'agit de régler la variable envPOSIX_BUILTINS
sur une valeur non nulle - mais j'oublie tout de suite. Dans tous les cas, cezsh
n'est pas un shell qui tente de se conformer à POSIX, et il est donc définitivement non standard. Ces deux coques évitent la compatibilité pour ce que certains croient être pratique.set -o posix
un essai réussi.Cela semble super facile (voir commentaires):
En plus ... Le test [-r file] n'indique pas si des données sont en attente de lecture (/ dev / null passe ce test (voir commentaires)).
Un petit nombre pour l'argument de délai d'attente (lecture -t) est requis ou les données qui nécessitent un calcul peuvent être manquées. Le test lisible ([-r fichier]) est requis ou la commande read se bombardera si le fichier n'est pas lisible. Cela ne lira en fait aucune donnée car le nombre d'octets est nul (lire -N 0).
la source
/proc/<pid>/fdinfo/<fd>
, qui répertorie tous les modes de fichiers ouverts sousflags:
- voir ici . Pour pourquoi votre 2ème partie (même après avoir corrigé l'erreur flagrante):read -t .1 -N0 <&4
ne dira pas s'il y a des données à lire sur fd 4: essayez simplement avec4</dev/null
.[ -r /proc/$$/fd/$FD ]
ne vous dit pas si le descripteur de fichier$FD
est lisible, mais si le fichier à partirexec 7>/tmp/foo; [ -r /proc/$$/fd/7 ] && echo fd 7 can be read from && cat <&7
La question est assez ancienne - mais de toute façon - pourquoi ne pas simplement utiliser les fonctions intégrées?
Production:
Donc, pour répondre à la question - suggérerait:
la source
-t
ne teste pas si un descripteur de fichier est valide, mais s'il est connecté à un tty. Ajoutez unecho yup |
à votre script, et dira que0 is INVALID FD
, alors qu'en fait c'est un fd très valide, un pipe.