Jak wyświetlić IP na ekranie logowania w Arch Linux

2

Udało mi się to zrobić w Ubuntu, edytując plik:

/etc/rc.local

i dodaj:

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

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

W Arch ten plik nie istnieje „/etc/rc.local”, a po przeszukaniu znalazłem, że muszę utworzyć ten plik:

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

Zawartość:

[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

Następnie utwórz „/etc/rc.local”.

Zawartość:

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

exit 0

Następnie spraw, aby był wykonywalny:

sudo chmod +x /etc/rc.local

I wreszcie rozpocznij / przetestuj:

sudo systemctl start rc-local.service

Błąd:

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.

Wyjście 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'.

Wyjście 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

Aktualizacja:

  1. Dodany #!/bin/bash do /etc/rc.local
  2. sudo systemctl daemon-reload
  3. sudo systemctl start rc-local.service
  4. Teraz nie dostaję żadnych błędów! ale:
  5. sudo systemctl status rc-local.service Wydajność:

    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.

Próbowano zrestartować komputer i przed zalogowaniem mówi:

rtnetlink answers network is unreachable

Na ekranie logowania: pokazuje „IP:” tylko bez pokazywania adresu IP komputera. Po zalogowaniu się i pingowaniu google na przykład internet działa bez problemu, a komputer jest dostępny za pośrednictwem sieci LAN.


  1. sudo env -i /etc/rc.local = Brak wyjścia
  2. ip route get 1 | awk '{print $NF;exit}' który jest używany w /etc/rc.local = 192.168.0.103

Wyjście 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

Edytowane /etc/systemd/system/rc-local.service: Usunięto cztery ustawienia po wykonaniu ExecStart. Próbowałem również zmienić: Type=forking

Stan nadal mówi: Active: inactive (dead)

Maro
źródło
Wygląda na to, że chcesz wyświetlić adres IP, a nie adres IP, o co prosiłeś w pytaniu. Masz tylko dwa możliwe adresy IP: IPv4 i IPv6.
Ron Maupin
@ RonMaupin, Przepraszamy za błąd, chcę wyświetlić wewnętrzny adres IP. Czy jest jakiś błąd w moich krokach lub kodzie bash?
Maro

Odpowiedzi:

0

Mam 99% pewności, że to dlatego, że nie wywołałeś interpretera w skrypcie.

/etc/rc.local :

#!/bin/bash

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

exit 0

To prawdopodobnie zadziała. Wiele osób jawnie wywołuje bash w swoich plikach systemowych; Zmodyfikowałem twój plik usługi. Wspominam o tym poniżej, ale 4 ustawienia są niepotrzebne (według mojej najlepszej wiedzy) i usunąłem je również tutaj:

/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

Powinieneś również użyć pełnej ścieżki do awk, ale to byłby inny błąd - jeszcze nie poszedłeś tak daleko w skrypt.

Jeśli to nie rozwiąże problemu, będziesz musiał przejść przez każdy jego fragment i zobaczyć, co działa samodzielnie. Środowisko systemowe jest bardzo rzadkie (podobne do rzeczy uruchamianych z crona, ale mniej środowiska). Rzeczy które zawsze praca przestaje działać z powodu pewnych ustawień środowiskowych, które są zawsze ustawiane, więc zapominamy, że nawet trzeba ją ustawić. Spróbuj wyodrębnić problem związany z tym. Oto kilka kroków izolacji:

  1. Wykonaj bezpośrednio (z sudo lub w powłoce roota dla każdego kroku) /etc/rc.local z terminala.

  2. Jeśli to działa, spróbuj wykonać go jako env -i /etc/rc.local Jeśli to nie zadziała, możesz próbować przekazywać wartości środowiskowe pojedynczo lub ustawić je jako „brutalne” (bardzo niechętne, ale gdybyś był tak skłonny, mógłbyś zrzucić wynik env w „normalnej” powłoce env | sed 's/^/export /g' | sed 's/=/='/g' | sed -e 's/$/'/g' > env_values.sh i jawnie ustaw te wartości w skrypcie. Musisz trochę przeskanować listę - będzie ona miała wartości połączenia ssh i inne wpisy sterowane zdarzeniami, które prawdopodobnie nic nie zepsują, ale zdecydowanie nie pomogą w anytowaniu).

  3. Jeśli nie jest tak, ponieważ bez względu na to, jak wykonasz rc.local, po prostu działa, usunąłbym twój systemowy plik usługi. Wypróbuj bez nich.

    • Ustawienie pozostałości po wyjściu nie ma tu znaczenia - jest to związane z używaniem tego do wywołania skryptu jednorazowego, który tworzy demony.
    • Ustawienie tty jest bardzo szczególnym przypadkiem i nie jest potrzebne.
    • Ustawienie limitu czasu 0 może spowodować zawieszenie systemów podczas wyłączania i włączania zasilania.
    • SysVStartPriority jest przestarzały na systemd ver & gt; 218+; arch jest włączony przynajmniej w 229.
  4. Spróbuj użyć @ Reboot cronjob . Bardzo podobne środowisko, ale uważam to za mniej „wybredne”. @reboot zastępuje zwykłą 5-gwiazdkową metodę pomiaru czasu (np. zamiast 0 0 0 * * po prostu umieszczasz @reboot), a Twój skrypt zostanie wywołany przy każdym uruchomieniu. Jeśli potrzebujesz dodatkowej pomocy przy zakładaniu cronjob, zdecydowanie mogę podać więcej szczegółów.

Nie ma nic złego w twojej metodzie uzyskiwania IP. Oto inna metoda wypróbowania, jeśli powoduje jakiekolwiek problemy. Twój jest prawdopodobnie lepszy. ma mniej zależności i na pewno czystsze, ale używam tego podejścia od lat bez problemu:

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"

Jeśli to się nie powiedzie, będziesz musiał przeczytać dokumentację systemową ... która, jak się prawdopodobnie odkryłeś, jest bardzo długa w przeliczaniu na słowa i niewiarygodnie niska na konkretnych informacjach. Daj mi znać, co się dowiesz, nawet jeśli te pomysły nie działają - w wynikach mogą być wskazówki.

Aktualizacja

Zgodnie z Twoją aktualizacją zmiany w usłudze umożliwiają poprawne działanie skryptu. Status, który otrzymujesz, jest normalny w przypadku jednorazowych usług systemowych, które są naprawdę skupione wokół procesów demona, które są uruchamiane, a ty tego nie robisz - więc (upraszczając to bardzo) zasadniczo mówiąc, że jest nieaktywny, oznacza to po prostu skrypt nie jest jeszcze uruchomiony, nie jest zaplanowany do uruchomienia i nie pojawił się żaden proces, który śledzi system - wszystko jest poprawne i w porządku. Fakt, że pokazuje, że niedawno został uruchomiony i zakończony dzięki SUCCESS, oznacza, że ​​działa.

Drugą kwestią jest czas względny. Krótka odpowiedź brzmi, że musisz zmienić plik usługi, dodając następujące dwa wpisy w [Jednostka]. To może po prostu praca . Jeśli nie, czytaj dalej.

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

Jest świetny artykuł na ten temat wymiana stosu Wydaje się, że zakryli każdy sposób, który może pójść źle, i sposób, w jaki może pójść dobrze w niewłaściwy sposób ... Nie będę się starał przekazać tego - po prostu wyślij to prosto od pozornego guru.

Alternatywne podejście, które ma tę zaletę, że rozzłości fanów systemowych

Jeśli takie podejście stanie się trudne lub niemożliwe z jakiegoś powodu, tutaj jest znacznie mniej elegancka metoda brutalnej siły, do której zwykle zwracam się, kiedy moja systemowa cierpliwość wypaliła się:

Możesz zmodyfikować skrypt, aby poczekał, aż adres IP stanie się dostępny, a nie zaplątuje się w problemy związane z czasem poprzedzającym. Jest to hack, ponieważ celowo wprowadzono nowe możliwości, które są wbudowane w systemd, ale to prawdopodobnie zrobiłbym.

Zaktualizowałem ten skrypt (próbowałem go uruchomić i znalazłem kilka problemów). Ten działa dobrze w moim systemie. Użyłem składni funkcji C na wywołaniu uśpienia i zapomniałem zwrócić coś z getIP; oba naprawione.

/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

I tak, używam tego regex $ iprgx cały czas - super pomocny.

Argonauts
źródło
Naprawdę doceniam twoją wspaniałą odpowiedź, wypróbowałem ją i opublikowałem wyniki w moim pytaniu w celu lepszego formatowania.
Maro
Pomyślałem, że za pierwszym będą ukryte problemy. Skrypt jest teraz uruchomiony; po uruchomieniu jest za wcześnie. W odpowiedzi udzielam więcej informacji
Argonauts
Nie ma teraz żadnych błędów, ale kiedy sprawdzam status, mówi: Aktywny: nieaktywny (martwy) 3 lata temu, czy może pozostać aktywny / uruchomiony na przykład przez kilka minut? więc rozwiązuje problem?
Maro
Zadałeś to pytanie, zanim zaktualizowałem odpowiedź, w której starałem się to trochę wyjaśnić. Zasadniczo status, który widzisz (oczekiwane jest nieaktywne (martwe), normalne zachowanie dla jednej usługi). Zrobił to, nie ma demonów, nie ma możliwości ponownego uruchomienia, zatrzymania itp., Więc jest dokładnie nazywany martwym Zabierz to, że działało pomyślnie - dla tego typu „SUKCES” jest najbardziej trafną informacją.
Argonauts
Dziękuję bardzo za każdą sekundę, na którą napisałeś swoją odpowiedź, bardzo mi pomogłem. dwie linie po [Unit] rozwiązałem to! Wielkie dzięki
Maro
2

Na CentOS 7 i Debian 8 (i może również inne), po prostu dodaj następującą linię do /etc/issue

My IP address: \4

i to rozwiąże adres IPv4 maszyny. Jeśli masz wiele interfejsów sieciowych i chcesz wybrać jeden konkretny, możesz go określić

My IP address: \4{eth0}
PaoloC
źródło