2

Я смог сделать в Ubuntu, отредактировав файл:

/etc/rc.local

и добавить:

IP=$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')

echo "IP: $IP" > /etc/issue

В Arch этот файл не существует "/etc/rc.local", и после некоторого поиска я обнаружил, что должен создать этот файл:

/etc/systemd/system/rc-local.service

Содержание:

[Unit]
Description=/etc/rc.local compatibility

[Service]
Type=oneshot
ExecStart=/etc/rc.local

TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
SysVStartPriority=99

[Install]
WantedBy=multi-user.target

Затем создайте "/etc/rc.local".

Содержание:

IP=$(/sbin/ip route get 1 | awk '{print $NF;exit}')
echo "IP: $IP" > /etc/issue

exit 0

Затем сделайте его исполняемым:

sudo chmod +x /etc/rc.local

И, наконец, начать / проверить:

sudo systemctl start rc-local.service

Получение ошибки:

Job for rc-local.service failed because the control process exited with error code.
See "systemctl status rc-local.service" and "journalctl -xe" for details.

Вывод systemctl status rc-local.service:

* rc-local.service - /etc/rc.local Compatibility
Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Fri 2016-06-10 02:52:17 AST; 1min 59s ago
Process: 760 ExecStart=/etc/rc.local (code=exited, status=203/EXEC)

Jun 10 02:52:17 maro systemd[1]: Starting /etc/rc.local Compatibility...
Jun 10 02:52:17 maro systemd[1]: rc-local.service: Control process exited, code=exited status=203
Jun 10 02:52:17 maro systemd[1]: Failed to start /etc/rc.local Compatibility.
Jun 10 02:52:17 maro systemd[1]: rc-local.service: Unit entered failed state.
Jun 10 02:52:17 maro systemd[1]: rc-local.service: Failed with result 'exit-code'.

Выходные данные journalctl -xe:

-- Unit rc-local.service has begun starting up.
Jun 10 02:52:17 maro systemd[760]: rc-local.service: Failed at step EXEC spawning /etc/rc.local: Exec format error
-- Subject: Process /etc/rc.local could not be executed
-- Defined-By: systemd

Обновить:

  1. Добавлено #!/bin/bash в /etc/rc.local
  2. sudo systemctl daemon-reload
  3. sudo systemctl start rc-local.service
  4. Теперь я не получаю никаких ошибок! но:
  5. sudo systemctl status rc-local.service Вывод:

    rc-local.service - /etc/rc.local Compatibility Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: disabled) Active: inactive (dead) since Fri 2016-06-10 13:13:04 AST; 3s ago Process: 488 ExecStart=/etc/rc.local (code=exited, status=0/SUCCESS)

    Jun 10 13:13:04 maro systemd[1]: Starting /etc/rc.local Compatibility... Jun 10 13:13:04 maro systemd[1]: Started /etc/rc.local Compatibility.

Пытался перезагрузиться и перед входом в систему пишет:

rtnetlink answers network is unreachable

На экране входа в систему: отображается «IP:» только без указания IP-адреса устройства. Например, после входа в систему и проверки связи с Google, интернет работает без проблем, и машина доступна через локальную сеть.


  1. sudo env -i /etc/rc.local = Нет данных
  2. ip route get 1 | awk '{print $NF;exit}' который используется в /etc/rc.local = 192.168.0.103

Вывод nav:

XDG_SESSION_ID=c2
TERM=xterm
SHELL=/bin/bash
SSH_CLIENT=192.168.0.100 64436 22
SSH_TTY=/dev/pts/0
USER=maro
MAIL=/var/spool/mail/maro
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
PWD=/home/maro
LANG=C
SHLVL=1
HOME=/home/maro
LOGNAME=maro
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
SSH_CONNECTION=192.168.0.100 64436 192.168.0.103 22
XDG_RUNTIME_DIR=/run/user/1000
_=/usr/bin/env

Отредактировано /etc/systemd/system/rc-local.service: удалены четыре параметра после ExecStart. Я также попытался изменить: Type=forking

Статус все еще говорит: Active: inactive (dead)

2 ответа2

2

В CentOS 7 и Debian 8 (и, может быть, также и в других) просто добавьте следующую строку в /etc/issue

My IP address: \4

и это будет преобразовано в IPv4-адрес компьютера. Если у вас есть несколько сетевых интерфейсов, и вы хотите выбрать один конкретный, вы можете указать его с помощью

My IP address: \4{eth0}
0

Я на 99% уверен, что это потому, что вы не вызвали переводчика в сценарии.

/etc/rc.local:

#!/bin/bash

IP=$(/sbin/ip route get 1 | awk '{print $NF;exit}')
echo "IP: $IP" > /etc/issue

exit 0

Это, вероятно, сработает. Многие люди также явно вызывают bash в своем системном файле; Я изменил ваш сервисный файл. Я упоминаю об этом ниже, но 4 из настроек являются ненужными (насколько мне известно), и я также удалил их здесь:

/etc/systemd/system/rc-local.service:

[Unit]
Description=/etc/rc.local compatibility

[Service]
Type=oneshot
ExecStart=/bin/bash /etc/rc.local

[Install]
WantedBy=multi-user.target

Вы также должны использовать полный путь к awk, но это было бы другой ошибкой - вы еще не углубились в сценарий.

Если это не помогло, вам придется пройтись по каждой части и посмотреть, что работает само по себе. Среда systemd очень скудна (похожа на вещи, запускаемые cron, но меньше среды). Вещи, которые всегда работают, перестают работать из-за каких-то условий среды, которые всегда установлены, поэтому мы забываем, что их даже нужно устанавливать. Так что попробуйте выделить для проблемы, связанной с этим. Вот несколько шагов изоляции:

  1. Непосредственно выполнить (с помощью sudo или в корневой оболочке для каждого шага) /etc/rc.local из терминала.

  2. Если это работает, попробуйте выполнить его как env -i /etc/rc.local Если это не сработает, вы можете попробовать передавать значения окружения по одному за раз, или сделать так, чтобы ваш сценарий 'brute force' установил их (сильно нахмурился) но если бы вы были настолько склонны, вы могли бы сбросить вывод env в «нормальную» оболочку:env | sed 's/^/export /g' | sed 's/=/='/g' | sed -e 's/$/'/g' > env_values.sh и явно установите эти значения в скрипте. Вам нужно немного почистить список - в нем будут значения ssh-соединения и другие записи, управляемые событиями, которые, вероятно, ничего не сломают, но определенно не помогут.

  3. Если это не так, потому что независимо от того, как вы выполняете rc.local, он просто работает, я бы удалил ваш файл службы systemd. Попробуйте это без них.

    • Параметр остатков после выхода здесь не имеет значения - это связано с использованием этого для вызова одноразового сценария, который порождает демонов.
    • Параметр tty является особенным случаем и не нужен.
    • Значение тайм-аута 0 может привести к зависанию систем во время включения и выключения питания.
    • SysVStartPriority устарела для systemd ver> 218+; арка, по крайней мере, вер 229.
  4. Попробуйте использовать @reboot cronjob. Очень похожая среда, но я нахожу ее менее «привередливой». @reboot заменяет обычный метод синхронизации с 5 звездочками (например, вместо 0 0 0 * * вы просто вводите @reboot), и ваш скрипт будет вызываться при каждой загрузке. Если вам нужна дополнительная помощь в настройке cronjob, я могу предоставить более подробную информацию.

Я ничего не вижу в вашем методе получения вашего IP IP. Вот другой метод, чтобы попробовать, если это вызывает какие-либо проблемы. Твой, наверное, лучше. имеет меньше зависимостей и, конечно, чище, но я использую этот подход в течение многих лет без проблем:

iprgx='(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
cat /etc/hostname | /usr/bin/host -4r | grep -Eo "$iprgx"

Если все это не поможет, вам придется прочитать документацию по systemd ... которая, как вы, вероятно, обнаружили, очень длинна по количеству слов и невероятно мала по конкретной информации. Дайте мне знать, что вы узнаете, даже если эти идеи не сработают - результаты могут быть подсказкой.

Обновить

Согласно вашему обновлению, изменения в сервисе позволяют скрипту работать правильно. Статус, который вы получаете, является нормальным для одноразового использования - системные сервисы действительно сосредоточены вокруг запускаемых процессов-демонов, а вы этого не делаете - поэтому (сильно упрощая) говорят, что это неактивно, просто означает, что скрипт он еще не запущен, не запланирован к запуску, и он не породил никаких процессов, которые отслеживает systemd - что все правильно и нормально. Тот факт, что он показывает, что он только что был запущен и завершился с УСПЕХОМ, означает, что он работает.

Второй вопрос - относительное время. Краткий ответ: вам нужно изменить служебный файл, добавив следующие две записи в поле [Единица]. Это может просто сработать. Если нет, то читайте дальше.

[Unit]
Wants=network-online.target
After=network-online.target

Существует прекрасная статья по этой конкретной проблеме на stackexchange. Кажется, они рассмотрели все пути, которые могут пойти не так, и пути, которые могут пойти не так, как надо ... Я не буду пытаться передать это - просто получите это прямо от очевидного гуру.

Альтернативный подход, который выгодно раздражает поклонников systemd

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

Вы можете изменить свой сценарий так, чтобы он ожидал, пока IP-адрес не станет доступен сам по себе, вместо того, чтобы запутаться в проблемах «до» или «после». Это хак, потому что он намеренно реализует возможности, встроенные в systemd, но это то, что я, вероятно, сделал бы.

Я обновил этот скрипт (попытался запустить его и обнаружил пару проблем). Этот отлично работает в моей системе. Я использовал синтаксис функции C при вызове сна и забыл на самом деле вернуть что-нибудь из getIP; оба исправлены.

/etc/rc.local

#!/bin/bash   

iprgx='(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'

# I put this into a function since you will be looping on it.
# the error you are seeing is from the ip call - I pipe the error to
# /dev/null to get rid of that annoyance.
getIP() {
  echo "IP=$(/sbin/ip route get 1 2>/dev/null | awk '{print $NF;exit}' | grep -Eo "$iprgx")"
}

# watchdog timer - bail if it doesn't resolve after some delta-T
wdTimer=1
IP=$(getIP)
#echo "($wdTimer) IP: $IP"
while [ "$IP" == "" ]; do
  # There's nothing special about .5 seconds - just seemed reasonable
  sleep 0.5
  IP=$(getIP)
  #echo "($wdTimer) IP: $IP"
  ((wdTimer++))
  # Arbitrarily chosen timeout of 20 * 0.5 = 10 seconds
  # You can have it wait as long as you want. I suggest not
  # setting the sleep time too low as you'll be hammering on the
  # ip utility fairly hardly in that case; not a huge deal regardless
  # I also had it log something to the syslog - your mileage may vary
  # with logger - there are alternative ways to do that.
  if [ "$wdTimer" -gt "20" ]; then
    # timeout
    logger -s "Timed out attempting to acquire LAN IP in rc.local"
    exit 1
  fi
done
#echo "IP: $IP" #> /etc/issue
exit 0

И да, я использую это регулярное выражение $ iprgx все время - очень полезно.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .