systemd: 직렬화된 시작

systemd: 직렬화된 시작

Ubuntu 17.04가 부팅에 실패하여 디버깅하고 싶습니다.

시작이 무작위로 실패하는데, 이는 경쟁 조건 때문이라고 생각됩니다.

systemd이로 인해 부팅 오류가 발생하는지 확인할 수 있도록 작업을 병렬화하지 않도록 요청할 수 있습니까 ?

답변1

해결 방법: 서비스를 수동으로 실행

나는 한때시작 시 충돌이 발생함. 내 경우에는 basic.target목표에 도달한 후 이전에 충돌이 발생했기 때문에 어떤 서비스 시작으로 인해 충돌이 발생했는지 multi-user.target알고 싶었습니다 .multi-user.target

먼저 basic.target루트 셸을 추가하도록 부팅을 예약합니다. 이 작업을 영구적으로 수행할 수 있습니다(부팅이 성공적이라고 가정).

systemctl set-default basic.target
systemctl enable debug-shell

서비스 debug-shell는 tty 9에서 루트 셸을 실행합니다.

systemd.unit=basic.target systemd.debug-shell커널 명령줄에 인수를 추가하면 동일한 효과를 얻을 수 있습니다. 예를 들어 Grub에서는 명령줄을 다음과 같이 편집합니다.

linux /vmlinuz-4.13.0-38-generic root=/dev/mapper/crypt-root ro systemd.unit=basic.target systemd.debug-shell

이 셸에서는 다음 스크립트를 실행하여 서비스를 하나씩 시작했습니다. 이것은 대부분 테스트되지 않았습니다(한 번 실행했는데 문제의 서비스에서 예상대로 충돌했습니다).

#!/bin/sh
wants=$(systemctl show -p Wants multi-user.target | sed 's/^Wants=//' | tr ' ' '\n' | sort)
log=/var/tmp/multi-user-steps-$(date +%Y%m%d-%H%M%S)

log () {
  echo "$* ..." | tee -a "$log"
  sync
  "$@"
  ret=$?
  echo "$* -> $ret" | tee -a "$log"
  sync
  return $ret
}

# systemd services
for service in $wants; do
  log systemctl start $service
  sleep 2
done

# upstart services
for conf in /etc/init/*.conf; do
  service=${conf##*/}; service=${service%.conf}
  log service ${service} start
  sleep 2
done

# sysvinit services
for service in /etc/rc3.d/S*; do
  log ${service} start
  sleep 2
done

추가 종속성 추가

다음 스크립트는 특정 대상의 직접적인 종속성인 시스템 단위에 대한 "이전" 종속성을 선언하여 특정 순서로 실행되도록 합니다. multi-user.target또는 에서 실행하고 싶을 수도 있습니다 basic.target.

알아채다이 스크립트는 일반적으로 작동하지 않습니다기존 종속성을 고려하지 않기 때문에 종속성 순환이 발생할 수 있습니다. 올바른 스크립트는 기존 종속성을 수집하고 토폴로지 정렬을 수행해야 합니다. 문제를 해결했으므로 계속 해결하고 싶지 않습니다. 누군가 자신의 필요에 맞게 수정하고 싶을 경우를 대비하여 게시합니다.

또한 이는 Upstart 및 SysVinit 서비스에 영향을 미치지 않습니다.

/etc달리기 전에 백업하세요! (저는 다음을 사용하는 것을 적극 권장합니다.관리자를 기다려주세요.)

#!/bin/sh
set -e

if [ $# -eq 0 ] || [ "$1" = "--help" ]; then
  cat <<EOF
Usage: $0 TARGET
Linearize the dependencies of a systemd target so it starts deterministically.
This scripts adds systemd unit files called linearize-for*.conf containing
extra Before= dependencies for each dependency of TARGET.
EOF
fi

service_dir=/etc/systemd/system
target=$1

wants=$(systemctl show -p Wants "$target" | sed 's/[^= ]*=//' |
                                            tr ' ' '\n' | sort)
previous=
for want in $wants; do
  [ -d "$service_dir/$want.d" ] || mkdir "$service_dir/$want.d"
  cat <<EOF >"$service_dir/$want.d/linearize-for-${target%.*}.conf"
[Unit]
Before=$previous
EOF
  previous=$want
done

관련 정보