2010-07-15 6 views
19

In un programma C posso scrivere argv [0] e il nuovo nome compare in un elenco ps.Come cambiare argv0 in bash in modo che il comando si mostri con un nome diverso in ps?

Come posso fare questo in bash?

+0

Vuoi dire che vuoi eseguire uno script di shell bash e avere il suo nome in * ps * come qualcosa di diverso da "bash"? – Karmastan

+0

Se scrivo uno script chiamato 'foo.sh', appare in _ps_ come foo.sh. Voglio vederlo come 'bar.sh'. – bstpierre

+0

dubito che scrivere argv0 sia effettivamente legale, specialmente se ciò che scrivi è più lungo dell'originale, ma ho bisogno di trovare un riferimento per questo – frankc

risposta

10

Ho avuto la possibilità di consultare il sorgente per bash e non sembra che ci sia supporto per la scrittura su argv [0].

25

È possibile farlo quando si esegue un nuovo programma tramite exec -a <newname>.

+1

+1: e per aggiungere a quanto sopra, potresti avere un "se $ 0 non è quello che voglio, quindi 'exec -a what_i_want'" in alto ... – eruciform

+1

Non sembra che abbia influire per me in Bash 4.0.33 –

+4

Sfortunatamente non influenza la * corrente * shell. Devi aprirne uno nuovo usandolo. –

6
(exec -a foo bash -c 'echo $0') 
+0

Ciò * riavvia * il processo. Non è come scrivere su argv [0] per cambiare il nome. – bstpierre

+1

Bene, forchetta una subshell, quindi sostituisce quella subshell con il processo avviato da 'exec'. Questo è quasi identico a quello che succede quando digiti semplicemente 'bash -c 'echo $ 0'' – chepner

0

Vorrei solo aggiungere che questo deve essere possibile in fase di esecuzione, almeno in alcuni ambienti. Assegnare $ 0 in perl su linux cambia ciò che appare in ps. Non so come sia implementato, comunque. Se riesco a scoprirlo, aggiornerò questo.

modifica: Sulla base di come perl lo fa, non è banale. Dubito che ci sia un bask integrato in fase di esecuzione ma non lo so per certo. Puoi vedere how perl does sets the process name at runtime.

5

Suppongo che tu abbia uno script di shell che desideri eseguire in modo che la stessa procedura di script abbia un nuovo argv[0]. Ad esempio (l'ho provato solo in bash, quindi lo sto usando, ma potrebbe funzionare altrove).

#!/bin/bash 

echo "process $$ here, first arg was $1" 
ps -p $$ 

L'output sarà simile a questo:

$ ./script arg1 
process 70637 here, first arg was arg1 
    PID TTY   TIME CMD 
70637 ttys003 0:00.00 /bin/bash ./script arg1 

Così ps mostra il guscio, /bin/bash in questo caso. Ora tentare la shell interattiva di exec -a, ma in una subshell in modo da non soffiare via la shell interattiva:

$ (exec -a MyScript ./script arg1) 
process 70936 here, first arg was arg1 
    PID TTY   TIME CMD 
70936 ttys008 0:00.00 /bin/bash /path/to/script arg1 

Woops, che mostra ancora /bin/bash. quello che è successo? Il exec -a probabilmente ha impostato argv[0], ma una nuova istanza di bash è stata avviata perché il sistema operativo leggeva #!/bin/bash nella parte superiore dello script. Ok, e se eseguissimo l'execing all'interno della sceneggiatura in qualche modo? Per prima cosa, abbiamo bisogno di un modo per scoprire se questa è la "prima" esecuzione dello script, o la seconda, exec istanza, altrimenti la seconda istanza eseguirà nuovamente, e avanti e avanti in un ciclo infinito. Quindi, è necessario che l'eseguibile per non sia un file con una riga #!/bin/bash nella parte superiore, per impedire al sistema operativo di modificare l'argomento desiderato [0]. Ecco il mio tentativo:

$ cat ./script 
#!/bin/bash 

__second_instance="__second_instance_$$" 
[[ -z ${!__second_instance} ]] && { 
    declare -x "__second_instance_$$=true" 
    exec -a MyScript "$SHELL" "$0" "[email protected]" 
} 

echo "process $$ here, first arg was $1" 
ps -p $$ 

Grazie a this answer, ho primo test per la variabile d'ambiente __second_instance_$$, sulla base del PID (che non cambia attraverso exec) in modo che non si scontrerà con altri script che utilizzano questa tecnica. Se è vuoto, presumo che questa sia la prima istanza ed esporto quella variabile d'ambiente, quindi exec. Ma, soprattutto, non eseguo questo script, ma eseguo direttamente il binario della shell, con questo script ($0) come argomento, passando anche tutti gli altri argomenti ([email protected]). La variabile di ambiente è un po 'un hack.

Ora l'output è questo:

$ ./script arg1 
process 71143 here, first arg was arg1 
    PID TTY   TIME CMD 
71143 ttys008 0:00.01 MyScript ./script arg1 

Questo è quasi arrivati.argv[0] è MyScript come desidero, ma è presente l'argomento aggiuntivo ./script, che è una conseguenza dell'esecuzione diretta della shell (anziché tramite l'elaborazione del sistema operativo #!). Sfortunatamente, non so come ottenere di meglio.

9

Solo per la cronaca, anche se non esattamente rispondere alla domanda del manifesto originale, questo è qualcosa di banale a che fare con zsh:

ARGV0=emacs nethack 
0

Copiare l'eseguibile bash per un nome diverso.

È possibile farlo nello script stesso ...

cp /bin/bash ./new-name 
PATH=$PATH:. 
exec new-name $0 

Se si sta tentando di far finta che non sei uno script di shell è possibile rinominare il sé script per qualcosa di fresco o anche "" (un singolo spazio) così

exec new-name " " 

eseguirà lo script bash e appare nella lista ps come solo new-name.

OK così chiamare uno script di "" è una pessima idea :)

In sostanza, per modificare il nome

bash script 

rename bash e rinominare lo script.

Se siete preoccupati, come il signor McDoom. a quanto pare è, sulla copia di un file binario con un nuovo nome (che è del tutto sicuro) si potrebbe anche creare un link simbolico

ln -s /bin/bash ./MyFunkyName 
./MyFunkyName 

In questo modo, il collegamento simbolico è quello che appare nella lista ps. (usa ancora PATH = $ PATH :. se non vuoi il ./)

+0

Spero che nessun nuovo arrivato abbia letteralmente rinominato bash e rinominato lo script. Questo sono sicuro che spezzerebbe molte molte cose! – mcdoomington

+0

:) inizia con "** Copia ** dell'eseguibile bash con un nome diverso." e i comandi sono chiari. Lo faccio parecchio se voglio un raccoglitore con un nome diverso, non interrompe nulla per cambiare il nome di un binario, chiaramente è necessario lasciare/bin/bash dove si trova. A volte i bins agiscono in modo diverso a seconda del nome utilizzato, ma solitamente hanno anche un comportamento predefinito. Lo faccio con bash molto da quando ho hackerato codice bash e compilato le mie versioni. – teknopaul

+0

Ciao Teknopaul, sì (l'ho letto e capito), ma sai come funzionano i campioni di copia e incolla SO - magari modifica la risposta per dire PERCHÉ hai copiato Bash su un altro nome;) Se qualcuno cambia il vero bash ...saranno in giro se si riavviano e non hanno prompt. – mcdoomington