En bash, je remarque que si une commande utilisant la redirection échoue, tous les programmes qui s'exécutent avant cela ne sont pas exécutés.
Par exemple, ce programme ouvre le fichier "a" et écrit 50 octets dans le fichier "a". Cependant, l'exécution de cette commande avec redirection vers un fichier avec des autorisations insuffisantes (~ root / log), ne produit aucun changement dans la taille du fichier de "a".
$ ./write_file.py >> ~root/log
-bash: /var/root/log: Permission denied
cdal at Mac in ~/experimental/unix_write
$ ls -lt
total 16
-rw-rw-r-- 1 cdal staff 0 Apr 27 08:54 a <-- SHOULD BE 50 BYTES
On pourrait penser que le programme fonctionnerait, capturer n'importe quelle sortie (mais aussi écrire dans le fichier "a"), puis échouer à écrire n'importe quelle sortie dans ~ root / log. Au lieu de cela, le programme n'est jamais exécuté.
Pourquoi cela et comment bash choisit-il l'ordre des "vérifications" qu'il effectue avant d'exécuter un programme? D'autres contrôles sont-ils également effectués?
ps J'essaie de déterminer si un programme exécuté sous cron s'est réellement exécuté lorsqu'il a été redirigé vers un fichier "permission refusée".
la source
stdout
pour faire exactement cela. Ainsi, vous ne verrez aucune sortie, même si votre programme s'est exécuté.write_file.py
programme et envoyez sa sortie à~root/log
bash:" Désolé, mais vous n'êtes pas autorisé à écrire dans ce fichier! "Le shell fait exactement ce qu'il doit faire. S'il ne peut pas faire ce que vous lui avez demandé de faire faire, il vous informe immédiatement pourquoi il y a un problème, vous donnant la possibilité de décider comment y faire face. Pour tous les responsables de bash savent, de très mauvaises choses peuvent se produire si vous exécutez cette commande et ne parvenez pas à enregistrer la sortie. Si c'était assez important que vous ayez désigné un endroit pour le sauvegarder, ce serait une erreur pour ASS | U | ME que c'était OK de courir sans enregistrer stdout.Réponses:
Il ne s'agit pas vraiment de commander des chèques, simplement l'ordre dans lequel le shell met les choses en place. Les redirections sont définies avant l'exécution de la commande; dans votre exemple, le shell essaie de s'ouvrir
~root/log
pour l'ajout avant d'essayer de faire quoi que ce soit impliquant./write_file.py
. Étant donné que le fichier journal ne peut pas être ouvert, la redirection échoue et le shell cesse de traiter la ligne de commande à ce stade.Une façon de le démontrer est de prendre un fichier non exécutable et de tenter de l'exécuter:
Cela montre que le shell ne regarde même pas
./demo
lorsque la redirection ne peut pas être configurée.la source
Depuis la page de manuel de bash, section REDIRECTION (souligné par moi):
Le shell essaie donc d'ouvrir le fichier cible pour
stdout
, ce qui échoue, et la commande n'est pas exécutée du tout.la source
Il convient de noter que le shell doit établir des redirections avant de démarrer le programme.
Considérez votre exemple:
Ce qui se passe dans le shell est:
fork()
; le processus enfant hérite des descripteurs de fichiers ouverts de son parent (le shell).fopen()
(l'expansion de) "~ root / log", etdup2()
cela à fd 1 (etclose()
le fd temporaire). En cas d'fopen()
échec, appelezexit()
pour signaler l'erreur au parent.exec()
"./write_file.py". Ce processus n'exécute plus aucun de nos codes (sauf si nous n'avons pas réussi à l'exécuter, auquel cas nous devonsexit()
signaler l'erreur au parent).wait()
à l'enfant de se terminer et de gérer son code de sortie (en le copiant$?
, au moins).Ainsi, la redirection doit se produire dans l'enfant entre
fork()
etexec()
: elle ne peut pas se produire avantfork()
car elle ne doit pas changer la sortie standard du shell, et elle ne peut pas se produire aprèsexec()
parce que le nom de fichier et le code exécutable du shell ont maintenant été remplacés par le programme Python . Le parent n'a pas accès aux descripteurs de fichiers de l'enfant (et même si c'était le cas, il ne pouvait garantir la redirection entreexec()
et la première écriture vers stdout).la source
Je suis désolé de vous informer que c'est tout le contraire. Le shell doit d'abord ouvrir ses E / S, puis passe le contrôle au programme.
tee
pourrait s'avérer utile dans ce cas:./write_file.py | tee -a ~root/log > /dev/null
la source