Como provar que o interpretador é / bin / bash quando chamado do cron

0

Isso tem sido um pouco de enigma para mim.

Quando eu tento os seguintes cronjobs individualmente:

* * * * * /bin/bash -c "readlink /proc/$$/exe >> /root/printenv"
* * * * * /bin/bash -c "readlink /proc/$PPID/exe >> /root/printenv"
* * * * * /bin/bash -c "readlink /proc/self/exe >> /root/printenv"
* * * * * /bin/bash -c "ps -h -o comm -p $$ >> /root/printenv"
* * * * * /bin/bash -c "echo $SHELL" >> /root/printenv

Eu obtenho os seguintes resultados respectivamente:

/bin/dash
/usr/sbin/cron
/bin/readlink
sh
/bin/sh

Parece que não consigo reportar /bin/bash em nenhuma circunstância quando chamado do cron assim.

Em um cronjob * * * * * /bin/bash -c "command" direto, como posso provar que " command " está sendo interpretado por /bin/bash (se for)?

Responda para referências futuras :

Alterar as aspas duplas para uma aspa simples retornou o shell certo:

* * * * * /bin/bash -c 'readlink /proc/$$/exe >> /root/printenv'

Retornado:

/bin/bash

Obrigado a todos os contribuidores para a resposta abaixo.

    
por Wadih M. 24.01.2017 / 14:38

2 respostas

3

Nesse caso, meu shell padrão é bash e acabei de executar um teste:

sh -c 'echo $0'

resultado: sh

sh -c "echo $0"

resultado: -bash

 bash -c 'echo $0'

resultado: bash

 bash -c "echo $0"

resultado: -bash

parece que você precisa usar aspas simples ' seguidas da -c switch

    
por 24.01.2017 / 15:10
1

O problema com todos os seus comandos é que você está usando a citação errada. Cada comando no crontab é um trecho de código shell, que é processado por um shell. O shell de processamento do comando crontab é definido pela configuração da variável SHELL no arquivo crontab, cujo padrão é /bin/sh .

Quando /bin/sh (ou qualquer shell compatível) executa o script /bin/bash -c "readlink /proc/$$/exe >> /root/printenv" , uma das etapas após a análise da linha de comando é executar qualquer variável ou substituição de comando. Há uma substituição de variável aqui: o $$ que está dentro de uma cadeia de aspas duplas. Portanto, $$ é substituído pelo ID do processo /bin/sh . Digamos que esse ID de processo seja 1234. O shell chamado pelo cron executa o comando /bin/bash com os argumentos -c e readlink /proc/1234/exe >> /root/printenv . A saída indica que /bin/sh é um link simbólico para /bin/bash .

Se você usar aspas simples em vez de aspas duplas, o shell invocado pelo cron não executará nenhuma substituição de variável e executará o comando /bin/bash com os argumentos -c e readlink /proc/$$/exe >> /root/printenv . Bash então analisa esse comando, realiza a substituição de $$ por seu próprio ID de processo e executa readlink com o argumento 1234 .

Observe que, dependendo do shell, a saída desse comando pode não ser o binário do shell, pode ser /bin/readlink . A razão é que existe uma otimização no bash (e vários outros shells): quando a última coisa que o shell precisa fazer é executar um comando externo, ele não executa esse comando em um processo filho, ele substitui o processo do shell imagem. (Executar um programa no Unix sempre funciona substituindo a imagem do processo por outros ; programas geralmente se dupliquem antes de fazer isso, mas não é uma obrigação.) Uma vez que o bash detecta que executar readlink é a última coisa que tem que fazer, ele executa readlink no mesmo processo 1234, então readlink /proc/1234/exe reports %código%. O Bash executa essa otimização se você acabou de executar um comando

bash -c 'readlink /proc/$$/exe'

mas não se houver um redirecionamento. Algumas conchas (por exemplo, traço) não realizam essa otimização. Algumas conchas, como ksh, são um pouco mais espertas e otimizam /bin/readlink , mas não otimizam, e. %código%. (Exercício: por que é impossível otimizar esse?)

    
por 25.01.2017 / 02:42

Tags