Réponse courte
Un programme peut connaître le nom sous lequel il a été invoqué ; il apprend son propre nom en examinant argv[0]
. Cela permet à des exécutables identiques de se comporter différemment sous des noms différents (exemple) ou à un seul exécutable de se comporter différemment lorsqu'il est appelé via des liens symboliques portant des noms différents (exemple).
Dans votre cas, l'exécutable systemctl
sait s'il est invoqué en tant que systemctl
, shutdown
ou autre chose. Il ajuste son comportement en conséquence.
Détails supplémentaires
Le tableau d'arguments est établi par le processus parent. C'est une convention (pas une exigence stricte) que argv[0]
est le nom. Le processus parent peut suivre ou non la convention. Lorsque vous exécutez systemctl
ou shutdown
à partir d'un shell, le shell est le parent et il suit la convention; en général, les shells suivent la convention.
Un exemple où la convention n'est pas suivie est le comportement de login
(et des outils qui tentent de le reproduire) : login
utilise un tiret en tête du zéroième argument pour informer un shell enfant qu'il est censé être un shell de connexion. Supposons que le shell de connexion soit Bash. Dans le shell, echo "$0"
vous montrera -bash
, malgré le fait que l'exécutable s'appelle bash
. Ce tiret initial est une autre convention.
Vous pouvez exécuter systemctl
avec un nom arbitraire. Certains noms sont spéciaux, ils modifient le comportement de systemctl
, c'est délibéré pour prendre en charge des liens symboliques comme celui que vous avez observé. Dans ma Debian 12, il s'agit (entre autres) de shutdown
et runlevel
. Vous n'avez pas besoin de créer un lien symbolique ou une copie pour transmettre un argv[0]
arbitraire à systemctl
, vous pouvez utiliser exec -a
de Bash.
Exemples d'utilisation d'un argv[0]
arbitraire
(Les exemples supposent que <code>systemctl</code> peut être atteint via <code>$PATH</code>. Fournissez le chemin complet si nécessaire.)
bash -c 'exec -a foo systemctl' # devrait se comporter comme systemctl classique car foo n'est pas un nom qui modifierait le comportement
bash -c 'exec -a shutdown systemctl --help' # devrait se comporter comme shutdown --help
bash -c 'exec -a runlevel systemctl' # devrait se comporter comme runlevel
En fait, vous pouvez utiliser un lien symbolique vers systemctl
(comme votre shutdown
) et transmettre quand même un argv[0]
arbitraire. Exemple :
bash -c 'exec -a runlevel shutdown' # devrait se comporter comme runlevel
Correction de votre "commande loufoque"
Votre "commande loufoque"
sudo systemctl -h +120
peut être corrigée comme ceci :
sudo bash -c 'exec -a shutdown systemctl -h +120'
Ici, le lien symbolique nommé shutdown
n'est pas du tout utilisé (il pourrait ne pas exister), l'exécutable systemctl
est invoqué directement ; il se comporte quand même comme shutdown
car nous transmettons le bon nom (shutdown
) comme argv[0]
.