Quel type de lien vers / bin / systemctl est / sbin / reboot?

Question stupide ici. Je vois que /sbin/reboot semble être un lien vers /bin/systemctl . Cependant, il ne se comporte pas comme un lien “simple” car appeler /bin/systemctl n’est pas la même chose que /sbin/reboot .

De plus, bien que /bin/systemctl ait une option de reboot , /sbin/reboot ne semble pas être un simple alias de /bin/systemctl reboot , car, par exemple, reboot --help affiche une aide spécifique /bin/systemctl reboot avec /bin/systemctl reboot --help (ou /bin/systemctl --help reboot ).

Alors, quel est ce lien et comment jeter un œil à sa définition?

Belle question, j’ai trouvé la réponse , fournie par @slm ♦ , sous Unix et Linux:

De nombreux programmes utilisent cette technique lorsqu’il existe un seul exécutable qui modifie son comportement en fonction de la manière dont il a été exécuté.

Il existe généralement une structure dans le programme appelée une instruction case / switch qui détermine le nom avec lequel l’exécutable a été appelé, puis appelle la fonctionnalité appropriée pour ce nom d’exécutable. Ce nom est généralement le premier argument reçu par le programme.

Lire les exemples…

Alors que dans la réponse originale, deux exemples avec C et Perl sont fournis, voici un exemple avec Bash. Dans Bash, le paramètre de position $0 contient le nom du script qui est exécuté. Créons donc un script simple, appelé program.sh et rendons-le exécutable:

 cat << EOF > program.sh && chmod +x program.sh #!/bin/bash echo "I was called as \"\${0##*/}\"" EOF 
  • \$ échappera à la signification particulière de $ dans cat lors de la création du script.

  • ${0##*/} affichera uniquement le nom de l’exécutable sans le chemin pendant l’exécution du script.

Ensuite, créons trois liens symboliques vers ce script:

 for link in call-{1..3}; do ln -s program.sh $link; done 

Maintenant, selon la façon dont nous appelons program.sh – directement ou par l’un des liens symboliques que nous avons créés – le résultat sera différent:

 $ ./program.sh I was called as "program.sh" $ ./call-1 I was called as "call-1" $ ./call-2 I was called as "call-2" $ ./call-3 I was called as "call-3" 

Comme le dit la pa4080 , il s’agit d’un lien symbolique normal et c’est systemctl lui-même qui vérifie le nom sous lequel il a été exécuté, afin de décider de l’action à exécuter. Ce genre de chose peut être réalisé avec n’importe quel mécanisme qui fait en sorte que le même fichier exécutable soit exécuté sous plusieurs noms; en pratique, cela se fait par l’utilisation de liens symboliques ou de liens physiques . Sur les systèmes GNU / Linux, comme Ubuntu, il est courant d’utiliser des liens symboliques à cette fin.

Dans Ubuntu, les versions avec systemd (qui comprend actuellement toutes les versions sockets en charge , à l’ exception de 14.04 LTS, qui utilise Upstart ), non seulement la commande de reboot mais également les commandes halt , poweroff , runlevel , shutdown et telinit sont toutes des liens symboliques vers /bin/systemctl :

 $ file /sbin/{halt,poweroff,reboot,runlevel,shutdown,telinit} /sbin/halt: symbolic link to /bin/systemctl /sbin/poweroff: symbolic link to /bin/systemctl /sbin/reboot: symbolic link to /bin/systemctl /sbin/runlevel: symbolic link to /bin/systemctl /sbin/shutdown: symbolic link to /bin/systemctl /sbin/telinit: symbolic link to /bin/systemctl 

Les actions précises que systemctl entreprend en fonction du nom que vous utilisez pour l’exécuter, ainsi que d’autres manières de spécifier ces actions, sont expliquées en détail dans cette excellente réponse de JdeBP à Quelle est la différence entre ces commandes permettant de supprimer un serveur Linux ? sur Unix.SE. Comme il est expliqué, ces commandes (sauf runlevel ) systemctl isolate ... de raccourci pour les commandes systemctl isolate ... avec ... remplacées par des cibles différentes.

Si cela vous intéresse, le code C qui considère le nom que vous avez utilisé pour appeler systemctl pour décider de l’action à exécuter est situé dans la fonction parse_argv définie dans systemctl.c , qui commence actuellement à la ligne 6972 de ce fichier. Pour le trouver, vous pouvez rechercher:

 static int parse_argv(int argc, char *argv[]) { 

Les parties pertinentes couvrent la plus grande partie de cette fonction, mais elle ressemble à peu près à ce fragment, continuant de la même manière, mais avec un code différent pour chaque chaîne, et avec quelques autres contrôles et logique de twigment:

  if (strstr(program_invocation_short_name, "halt")) { arg_action = ACTION_HALT; return halt_parse_argv(argc, argv); } else if (strstr(program_invocation_short_name, "poweroff")) { arg_action = ACTION_POWEROFF; return halt_parse_argv(argc, argv); } else if (strstr(program_invocation_short_name, "reboot")) { 

D’autres exemples de commandes qui examinent comment ils ont été appelés à (parfois) agir différemment incluent vim , qui se comporte différemment lorsqu’il est exécuté avec vim , ex , view , gvim , gview et plusieurs autres; ip , voir cette question ; gksu , voir cette question ; less , qui change d’apparence s’il est nommé more (mais vous permet quand même de faire défiler dans les deux sens, contrairement à Ubuntu); busybox ; et la plupart des shells de type Bourne , tels que bash et zsh , qui se comportent automatiquement de manière plus compatible avec les exigences POSIX de sh s’ils sont exécutés en tant que sh .