O conteúdo do arquivo / proc / PID / cmdline depende do script shebang?

4

Eu tenho um script bash chamado test.sh , que inicio com startproc . Caso eu use #!/usr/bin/env bash shebang em test.sh , o arquivo /proc/<PID>/cmdline será exibido:

SERVER:~ # cat /proc/29481/cmdline
bash/root/user/test.shSERVER:~ # 
SERVER:~ # 

Agora, quando altero a linha shebang para #!/bin/bash , o arquivo /proc/<PID>/cmdline é o seguinte:

SERVER:~ # cat /proc/29729/cmdline
/bin/bash/root/user/test.shSERVER:~ # 
SERVER:~ # 

O que causa esse comportamento? O conteúdo do arquivo /proc/<PID>/cmdline depende do script shebang? O problema é que, no caso da antiga opção checkproc , killproc ou startproc não são capazes de detectar o serviço test.sh . Eu uso o openSUSE 11.4 com sysvinit-tools-2.88-37.47.1.x86_64 .

    
por Martin 08.12.2015 / 18:59

2 respostas

4

Sim, o cmdline irá variar dependendo de exatamente qual exec* de chamada do sistema foi feita, e um caminho totalmente qualificado pode ser diferente de qual env(1) aparece na pesquisa de caminho.

bash-4.1$ cat aaa
#!/bin/bash
xxd /proc/$$/cmdline
bash-4.1$ cat bbb
#!/usr/bin/env bash
xxd /proc/$$/cmdline
bash-4.1$ ./aaa
0000000: 2f62 696e 2f62 6173 6800 2e2f 6161 6100  /bin/bash../aaa.
bash-4.1$ ./bbb
0000000: 6261 7368 002e 2f62 6262 00              bash../bbb.
bash-4.1$ 

strace mostra os detalhes:

bash-4.1$ strace ./aaa 2>&1 | grep exec
execve("./aaa", ["./aaa"], [/* 57 vars */]) = 0
bash-4.1$ strace ./bbb 2>&1 | grep exec
execve("./bbb", ["./bbb"], [/* 57 vars */]) = 0
execve("/sbin/bash", ["bash", "./bbb"], [/* 57 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/sbin/bash", ["bash", "./bbb"], [/* 57 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/local/sbin/bash", ["bash", "./bbb"], [/* 57 vars */]) = -1 ENOENT (No such file or directory)
execve("/bin/bash", ["bash", "./bbb"], [/* 57 vars */]) = 0
bash-4.1$ 

Se este for um script somente do Linux, a localização de bash provavelmente não variará (exceção: há um depósito de software de algum tipo que inclui bash , em outro lugar). Portanto, usar o caminho completo provavelmente faz mais sentido, já que isso evita env(1) em busca de caminhos e ganha compatibilidade com as ferramentas init.

    
por 08.12.2015 / 19:16
1

A linha de comando de um processo consiste nos elementos do parâmetro argv do execve chamada do sistema. Esse parâmetro é uma matriz numerada de 0, em que os elementos de número 1 a n são os argumentos transmitidos ao chamar o comando, e o elemento 0 é escolhido pelo shell ou outro programa que emite a chamada execve . Convencionalmente, o elemento 0 é a string usada para designar o comando.

Linhas Shebang são processadas pelo kernel. O kernel insere um argumento 0, que é o caminho especificado após o prefixo mágico #! . Portanto, se você executar /root/user/test.sh com o argumento foo de startproc , então startproc fará uma chamada execve com dois argumentos 0 = /root/user/test.sh , 1 = foo . Quando /root/user/test.sh começa com /bin/bash , o kernel vê o shebang em /root/user/test.sh e reescreve a lista de argumentos como 0 = /bin/bash , 1 = /root/user/test.sh , 2 = foo .

Se a linha shebang for #!/bin/env bash , o kernel inserirá dois itens na lista de argumentos: o programa e o argumento. (O Linux é limitado a um único argumento aqui.) Portanto, neste caso, a invocação é transformada em 0 = /bin/env , 1 = bash , 2 = /root/user/test.sh , 3 = foo . O programa env faz seu trabalho e emite uma nova chamada de sistema execve com 0 = bash (respeitando a convenção de que o argumento 0 é o caminho usado para designar o comando), 1 = /root/user/test.sh , 2 = foo .

Em todos os casos, /root/user/test.sh será o primeiro argumento do processo.

    
por 09.12.2015 / 02:27