[ "$BASH" != "/bin/sh" ]

 ( bAndie9100 | 2018. november 14., szerda - 12:50 )

Ez egy bejegyzés a Debiános base-files által szállított /etc/profile szkript és a bash közti kooperációs bugról.

Az /etc/profile-ban vagy egy olyan kondíció hogy if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ], ami arra hivatott, hogy ha a bash szimulált sh módban fut (ld. man: "If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible [...]", akkor ne töltse be a /etc/bash.bashrc fájlt.

Vizsgálatom szerint viszont a $BASH változó nem csak akkor veszi fel a "/bin/sh" értéket, ha "sh" néven indítottuk a bash-t. Aki nem tudná, az hogy "milyen néven" indítunk egy processzt, azaz a programm nulladik argumentuma, az nem feltétlen azonos a programm fájl nevével, hanem futtatáskor felülírható (ld. execve(2), és a bash built-in exec "-a" kapcsolója).

Nos az én use case-em az volt, hogy rootként, login shellként indítsam a bash-t és úgy, hogy a pam_env rutinja lefusson, plusz a default login shell maradjon változatlan, ami a passwd-ben van. Erre a su parancsot választottam, mert az feldolgozza a pam stack-et a session fázisban és felülbírálható a target user default login shellje ("-s /bin/bash"). Az egyetlen akadály az volt, hogy nem tudja paraméterezni a futtatandó programmot, amit egyébként a shell helyett futtat; ha sima "-c"-vel parancsként futtatnám a "bash --login"-t, akkor viszont ugye a default sh-n keresztül indítja, ami először is felesleges indirekció, másodszor meg töri a bash job-control képességét.

Tehát se plusz argumentum, se a nulladik arg felülbírálását nem támogatja a su. Nem gond, még mindig csinálhatok egy szimlinket "/bin/-bash" néven és kihasználom, hogy a bash login shellnek érzi magát ha az argv0 kötőjellel kezdődik (ld. shell.c: set_shell_name() a bash forrásában). Rendben, a su "-bash" néven futtatja a /bin/-bash -ra linkelt /bin/bash -t.

A következő fok a $BASH változó meghatározása. Ezt a variables.c get_bash_name() függvénye végzi, ami interaktív mód és relatív útvonalas argv0 mellett az aktuális user passwd-ből kiolvasott default login shelljére értékelődik ki. Mellékesen nem is tudom, van-e értelme abszolút útvonalnak az argv0-ban; ha lenne, akkor viszont megint nem klappolna a helyzet, mert a bash a kötőjelet nem a basename(argv0) elején várja, hanem az immár abszolút útvonalas argv0 ÉS a basename(argv0) elején IS (ld. set_shell_name()), ami eléggé nonsense szagú. Tehát a $BASH ezen viselkedése szerintem bugos. Már annál is inkább, mert a man szerint: "BASH Expands to the full file name used to invoke this instance of bash."

A full file névre ellenőrizni /etc/profile-ből meg szintén nem feltétlenül vág egybe a "be kéne-e tölteni a bashrc-t?" kérdés vizsgálatával.
Ezért részemről a fenti feltételvizsgálatot if [ "$BASH" -a ! "$POSIXLY_CORRECT" ]-ra változtatom.