Comment tester de manière non invasive l'accès en écriture à un fichier?

20

Dans un script shell, comment puis-je tester facilement et de manière non invasive l' accès en écriture à un fichier sans réellement tenter de modifier le fichier?

Je pourrais analyser la sortie de stat, mais cela semble vraiment complexe, et peut-être fragile, bien que je ne sois pas sûr de la différence de sortie des statistiques selon les implémentations et l'heure.

Je pourrais ajouter à la fin du fichier et voir si cela réussit, mais c'est potentiellement dangereux, pour deux raisons auxquelles je peux penser:

  1. Je dois maintenant supprimer l'addition, et dans le cas où un autre processus écrit dans le fichier, cela devient immédiatement non trivial car ma ligne n'est plus la dernière.
  2. Tout processus de lecture du fichier peut avoir des exigences arbitraires sur le contenu de ce fichier, et j'ai peut-être simplement cassé cette application.
user50849
la source

Réponses:

29

Utilisez simplement le wdrapeau - de l' testutilité:

[ -w /path/to/file ] && echo "writeable" || echo "write permission denied"

Notez que si vous allez écrire dans le fichier plus tard, il est toujours possible que vous ne puissiez pas y écrire. Le fichier peut avoir déplacé, les autorisations ont changé, etc. Il peut également arriver que -wDétecte autorisations d' écriture , mais d'autres facteurs intervient pour rendre le fichier en lecture seule .

le chaos
la source
1
Bien sûr! J'aurais dû penser à vérifier la page de manuel de test. Je vous remercie.
user50849
1
@qweilun c'est un shell intégré, mais vous pouvez afficher la page de manuel via man testouman [
chaos
5
@chaos Il s'agit à la fois d'un shell intégré et d'un exécutable externe - essayeztype -a
Volker Siegel
1
Par la sourcetest utilise euidaccessqui vérifie simplement les bits d'autorisation . N'y a-t-il pas d'autres facteurs (par exemple SELinux) qui pourraient interdire l'accès en écriture?
zamnuts
2
@BroSlow &&et ||ont la même priorité. Ils sont évalués de gauche à droite.
Wildcard
11

Une autre approche:

if >> /path/to/file
then
    echo "writeable"
else
    echo "write permission denied"
fi

Cela tentera d'ouvrir le fichier pour l'ajout et, si cela réussit, d' exécuter aucune commande (c'est-à-dire d' exécuter une commande nulle ) avec une sortie dans le fichier. 

Attention, cela crée un fichier vide s'il n'existait pas.

L' -wopérateur de la testcommande peut simplement faire un stat , puis essayer de déterminer s'il semble que vous devriez y avoir accès. Mon alternative (ci-dessus) est plus fiable que l' testapproche dans certaines conditions spéciales, car elle oblige le contrôle d'accès à être effectué par le noyau plutôt que par le shell. Par exemple,

  • si le fichier se trouve sur un système de fichiers non Unix - en particulier s'il est monté à distance à partir d'un serveur de fichiers non Unix - car il statpeut renvoyer une valeur de mode trompeuse.
  • si le fichier se trouve sur un système de fichiers monté en lecture seule.
  • si le fichier a une ACL et que le mode donne l'impression que vous devriez y avoir accès, mais l'ACL le refuse, ou vice versa.
  • si un cadre de sécurité (AppArmor, SELinux,…) refuse l'accès au fichier.
G-Man dit «Réintègre Monica»
la source
3
Je viens de tester cela (sur Debian). Aucune des deux périodes n'a été modifiée, et c'est ainsi que cela devrait fonctionner sur n'importe quel Unix. L'heure d'accès ne doit être mise à jour que si vous lisez à partir du fichier, l'heure de modification ne doit être mise à jour que si vous écrivez dans le fichier. Ce code ne fait ni l'un ni l'autre. @Schwern: avez-vous une référence pour votre déclaration? Avez-vous essayé?
G-Man dit `` Réintègre Monica ''
2
PS @muru: J'ai juste essayé touchun fichier que je possédais mais auquel je n'avais pas accès en écriture, et il a réussi. Je suppose que c'est chmodle fichier et chmodle récupérer. Il touchsemble donc absolument inutile de répondre à la question.
G-Man dit `` Réintègre Monica ''
2
@ G-Man ah, c'est intéressant. L'IIRC vima ce comportement de changer rapidement les autorisations lorsqu'il est forcé d'écrire sur des fichiers en lecture seule. J'ai vérifié avec strace, touch« s openéchoue avec EACCES, mais l'appel après utimensatSucceeds, ce qui est la raison pour laquelle je pense que touchsur l'ensemble des sorties avec succès.
muru
2
@muru: Merci d'avoir vérifié cela. utimensat(2)dit: « exigences d'autorisations: 1. accès en écriture (ou) 2. utilisateur effectif de l'identification de l' appelant doit correspondre au propriétaire du fichier, .... »
G-Man dit « Réintégrer Monica »
3
Autres problèmes comme pour Champignac: >> filen'est pas portable (par exemple, exécute le NULLCMD en zsh), utilisez true >> fileplutôt. Et si le fichier est un tube nommé, il a des effets secondaires désagréables.
Stéphane Chazelas
3

G-man a raison: [ -w ]ne dira pas toujours la vérité. Ici pour faire face à un fichier inexistant et à un message d' autorisation refusée du shell:

( [ -e /path/to/file ] && >> /path/to/file ) 2> /dev/null && 
  echo writable || 
  echo not writable

Mise à jour : semble effrayant, non? Et bien ça l'est. Hmm ... comment le formuler ... NE L'UTILISEZ PAS, à moins que vous ne sachiez parfaitement que vous êtes dans les conditions qu'il demande de fonctionner comme prévu. Voir le commentaire de Stéphane.

Que conclure alors? Même si [ -w ]elle ne dit pas la vérité, c'est la seule commande qui est destinée à faire le travail. Si ce n'est pas le cas, eh bien, nous le blâmerons, rédigerons des rapports de bogues et cela fonctionnera à l'avenir. Mieux vérifier les conditions de fonctionnement et d'utilisation [ -w ]; écrire du code spécial pour des cas spéciaux. Les solutions de contournement ont leurs propres conditions.

[ -w /path/to/file ]

est le meilleur a priori .

Champignac
la source
3
Si le fichier est un canal nommé, cela se bloquera s'il n'y a pas de lecture, et même s'il y a un lecteur, cela aura des effets secondaires désagréables. test -wdans la plupart des implémentations, l'utilisation access(2)devrait donc être suffisante pour tester les autorisations.
Stéphane Chazelas