Que tipo de link para / bin / systemctl é / sbin / reboot?

5

Pergunta estúpida aqui. Vejo que /sbin/reboot parece ser um link para /bin/systemctl . No entanto, ele não se comporta como um link "simples" porque chamar /bin/systemctl não é o mesmo que /sbin/reboot .

Além disso, embora /bin/systemctl tenha uma opção reboot , /sbin/reboot não parece ser um alias simples para /bin/systemctl reboot , porque, por exemplo, reboot --help imprime uma ajuda específica que não pode ser alcançada com /bin/systemctl reboot --help (ou /bin/systemctl --help reboot ).

Então, qual é esse link e como dar uma olhada em sua definição?

    
por P-Gn 11.04.2018 / 10:20

2 respostas

4

Boa pergunta, encontrei a resposta , fornecida por @slm ♦ , no Unix & Linux Q & A:

Many programs make use of this technique where there is a single executable that changes its behaviour based on how it was executed.

There's typically a structure inside the program called a case/switch statement that determines the name the executable was called with and then will call the appropriate functionality for that executable name. That name is usually the first argument the program receives.

Read the examples...

Enquanto na resposta original são fornecidos dois exemplos com C e Perl, aqui está um exemplo com o Bash. No Bash, o parâmetro posicional $0 contém o nome do script que é executado. Então vamos criar um script simples, chamado program.sh e torná-lo executável:

cat << EOF > program.sh && chmod +x program.sh
#!/bin/bash
echo "I was called as \"\${0##*/}\""
EOF
  • \$ escapará do significado especial de $ dentro de cat durante a criação do script.

  • ${0##*/} produzirá apenas o nome do executável sem o caminho durante a execução do script.

Em seguida, vamos criar três links simbólicos para esse script:

for link in call-{1..3}; do ln -s program.sh $link; done

Agora, dependendo de como chamamos program.sh - diretamente ou de qualquer um dos links simbólicos que criamos, a saída será diferente:

$ ./program.sh 
I was called as "program.sh"

$ ./call-1 
I was called as "call-1"

$ ./call-2
I was called as "call-2"

$ ./call-3
I was called as "call-3"
    
por pa4080 11.04.2018 / 10:37
2

Como pa4080 diz , é apenas um normal link simbólico e systemctl em si é o que verifica o nome que foi executado como, a fim de decidir qual ação executar. Esse tipo de coisa pode ser alcançado com qualquer mecanismo que faça com que o mesmo arquivo executável seja executado sob vários nomes; na prática, isso é conseguido através do uso de links simbólicos ou links físicos . Em sistemas GNU / Linux, como o Ubuntu, é mais comum usar links simbólicos para esse propósito.

Nas versões do Ubuntu com systemd (que atualmente inclui todos os suportados versões exceto 14.04 LTS, que usa Upstart ), não apenas o comando reboot , mas também o halt , poweroff , runlevel , shutdown e telinit são todos links simbólicos para /bin/systemctl :

$ file /sbin/{halt,poweroff,reboot,runlevel,shutdown,telinit}
/sbin/halt:     symbolic link to /bin/systemctl
/sbin/poweroff: symbolic link to /bin/systemctl
/sbin/reboot:   symbolic link to /bin/systemctl
/sbin/runlevel: symbolic link to /bin/systemctl
/sbin/shutdown: symbolic link to /bin/systemctl
/sbin/telinit:  symbolic link to /bin/systemctl

As ações precisas systemctl realizadas com base no nome usado para executá-las, bem como outras maneiras de especificar essas ações, são explicadas em detalhes em esta excelente resposta por JdeBP para Qual é o diferença entre esses comandos para derrubar um servidor Linux? em Unix.SE . Como explicado, esses comandos (exceto runlevel ) operam como abreviação para comandos systemctl isolate ... com ... substituído por destinos diferentes.

Caso esteja interessado, o código C que considera qual nome você usou para invocar systemctl ao decidir qual ação executar está localizado na função parse_argv definida em systemctl.c , que atualmente inicia na linha 6972 desse arquivo. Para encontrá-lo, você pode pesquisar por:

static int parse_argv(int argc, char *argv[]) {

As partes relevantes abrangem a maior parte dessa função, mas tudo se parece com esse fragmento, continuando de forma semelhante, mas com código diferente para cada string, e com algumas outras verificações e lógica de ramificação:

                if (strstr(program_invocation_short_name, "halt")) {
                        arg_action = ACTION_HALT;
                        return halt_parse_argv(argc, argv);
                } else if (strstr(program_invocation_short_name, "poweroff")) {
                        arg_action = ACTION_POWEROFF;
                        return halt_parse_argv(argc, argv);
                } else if (strstr(program_invocation_short_name, "reboot")) {

Outros exemplos de comandos que examinam como eles foram invocados para (às vezes) agir de forma diferente incluem vim , que se comporta de maneira diferente quando executado como vim , ex , view , gvim , gview e vários outros; ip , veja esta questão ; gksu , veja essa pergunta ; less , que altera sua aparência se for nomeado more (mas ainda permite rolar bidirecionalmente, ao contrário do Ubuntu more ); busybox ; e mais conchas estilo Bourne , como bash e zsh , que se comporta automaticamente de forma mais compatível com os requisitos POSIX para sh se executado como sh .

    
por Eliah Kagan 11.04.2018 / 17:42