Какая ссылка на/bin/systemctl является/sbin/reboot?

Глупый вопрос здесь. Я вижу это /sbin/reboot кажется, ссылка на /bin/systemctl. Однако это не ведет себя как "простая" ссылка потому что вызов /bin/systemctl не то же как /sbin/reboot.

Кроме того, хотя /bin/systemctl действительно имеет a reboot опция, /sbin/reboot кажется, не простой псевдоним к /bin/systemctl reboot, потому что, например, reboot --help печатает определенную справку, которая не может быть достигнута с /bin/systemctl reboot --help (или /bin/systemctl --help reboot).

Таким образом, какова эта ссылка и как посмотреть на ее определение?

7
задан 11 April 2018 в 01:20

2 ответа

Деликатный вопрос, я нашел ответ, предоставленный @slm ♦, на Unix & Linux Q&A:

Много программ используют эту технику, где существует единственный исполняемый файл, который изменяет его поведение на основе того, как это выполнялось.

Обычно существует структура в программе, названной случаем/оператором переключения, который определяет имя, которым с исполняемым файлом назвали и затем назовет соответствующую функциональность для того исполняемого имени. То имя обычно является первым аргументом, который получает программа.

Считайте примеры...

В то время как в исходном ответе предоставлены два примера с C и Perl, вот пример с Bash. В Bash позиционный параметр $0 содержит название сценария, который выполняется. Поэтому давайте создадим простой сценарий, названный program.sh и сделайте это исполняемым файлом:

cat << EOF > program.sh && chmod +x program.sh
#!/bin/bash
echo "I was called as \"\${0##*/}\""
EOF
  • \$ выйдет из особого значения $ в cat во время создания сценария.

  • ${0##*/} произведет только название исполняемого файла без пути во время выполнения сценария.

Затем давайте создадим три символьных ссылки на тот сценарий:

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

Теперь, в зависимости от того, как мы звоним program.sh - непосредственно или любой из символьных ссылок, которые мы создали - вывод будет отличаться:

$ ./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"
6
ответ дан 23 November 2019 в 06:31

Как pa4080 говорит, это - просто нормальная символьная ссылка, и systemctl самостоятельно то, что проверяет то, что называет его, был выполнен как, для решения что действие работать. Этот вид вещи может быть достигнут с любым механизмом, который заставляет тот же исполняемый файл быть выполненным под несколькими именами; на практике это достигается с помощью символьных ссылок или жестких ссылок. В системах GNU/Linux, как Ubuntu, наиболее распространено использовать символьные ссылки с этой целью.

В выпусках Ubuntu с systemd (который в настоящее время включает все поддерживаемые версии кроме 14.04 LTS, который использует Выскочку), не просто reboot команда, но также и halt, poweroff, runlevel, shutdown, и telinit команды являются всеми символьными ссылками на /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

Точные действия systemctl предпринимает на основе имени, которое Вы используете для выполнения его, а также другие способы, которыми можно указать те действия, объяснены подробно в этом превосходном ответе JdeBP к тому, Каково различие между этими командами для перевода в нерабочее состояние сервера Linux? на Unix. SE. Как это объясняет, эти команды (кроме runlevel) действуйте в качестве сокращения от systemctl isolate ... команды с ... замененный различными целями.

В случае, если Вам интересно, код C, который рассматривает то, что называет Вас, раньше вызывал systemctl в решении, что действие работать расположен в parse_argv функция, определяемая в systemctl.c, который в настоящее время запускает на строке 6972 из того файла. Для нахождения его, можно искать:

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

Соответствующие части охватывают большую часть той функции, но все это примерно напоминает этот фрагмент его, продолжаясь так же, но с другим кодом для каждой строки, и с некоторыми другими проверками и переходящей логикой:

                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")) {

Другие примеры команд, которые исследуют, как они были вызваны, чтобы (иногда) действовать по-другому, включают vim, который ведет себя по-другому, когда выполнено как vim, ex, view, gvim, gview, и несколько других; ip, посмотрите этот вопрос; gksu, посмотрите тот вопрос; less, который изменяет его появление, если названо more (но все еще позволяет Вам прокрутить двунаправлено, в отличие от Ubuntu more); busybox; и большинство оболочек стиля Границы, такой как bash и zsh, которые автоматически ведут себя более совместимо с требованиями POSIX для sh если выполнено как sh.

2
ответ дан 23 November 2019 в 06:31

Другие вопросы по тегам:

Похожие вопросы: