it-swarm-ko.tech

쉘을 사용하여 초기화 시스템 감지

이것은 운영 체제 감지와 더 관련이있을 수 있지만 특히 시스템에서 현재 사용중인 init 시스템이 필요합니다.

Fedora 15와 Ubuntu는 이제 systemd를 사용하고, Ubuntu는 Upstart (15.04까지 오랜 시간 기본값)를 사용했지만 다른 시스템은 System V의 변형을 사용합니다.

크로스 플랫폼 데몬으로 작성중인 응용 프로그램이 있습니다. init 스크립트는 configure에 전달 될 수있는 매개 변수를 기반으로 동적으로 생성됩니다.

내가하고 싶은 것은 그들이 사용하는 특정 init 시스템에 대한 스크립트 만 생성하는 것입니다. 이런 식으로 설치 스크립트를 루트없이 매개 변수없이 합리적으로 실행할 수 있으며 데몬을 자동으로 "설치"할 수 있습니다.

이것이 내가 생각해 낸 것입니다.

  • / bin에서 systemd, upstart 등 검색
  • / proc/1/comm을 systemd, upstart 등과 비교하십시오.
  • 사용자에게 물어보세요

이 작업을 수행하는 가장 좋은 교차/플랫폼 방법은 무엇입니까?

관련 종류 bash에 의존하여 * nix의 대다수에 의존 할 수 있습니까, 아니면 배포/OS에 의존 할 수 있습니까?

대상 플랫폼 :

  • 맥 OS
  • 리눅스 (모든 배포판)
  • BSD (모든 버전)
  • Solaris, Minix 및 기타 * nix
96
beatgammit

두 번째 질문에 대한 답은 no 이며 휴대용 셸 프로그래밍 리소스 를 살펴보십시오.

첫 번째 부분은-우선, 조심해야합니다. 나는 몇 가지 테스트를 수행하여 확인하십시오-누군가 does have systemd (예를 들어) 설치되었다고해서 이것이 실제로는 아닙니다 기본 init로 사용됩니다. 또한 /proc/1/comm 다양한 init 프로그램을 일부 설치하면 자동으로 /sbin/init symlink 하드 링크 또는 메인 프로그램의 이름이 바뀐 버전.

아마도 가장 유용한 것은 init 스크립트 유형을 보는 것입니다. 실행 스크립트에 관계없이 실제로 작성하는 스크립트 유형이기 때문입니다.

참고로 Linux 및 BSD 시스템과 호환되는 init 스크립트의 구조를 제공하는 OpenRC 도 살펴볼 수 있습니다.

30
rozcietrzewiacz

나는이 문제를 직접 시작했고 몇 가지 테스트를하기로 결정했습니다. 나는 각 배포판에 대해 개별적으로 패키지해야한다는 답변에 전적으로 동의하지만 때로는 그것을 막는 실질적인 문제가 있습니다 (인력뿐만 아니라).

따라서 "자동 감지"를 원하는 사람들을 위해 여기에서 제한된 배포판 (더 자세한 내용)을 발견했습니다.

  • 다음과 같이 시작을 알려줄 수 있습니다.

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
    
  • Systemd는 다음에서 알 수 있습니다.

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
    
  • Sys-v init는 다음에서 알 수 있습니다.

    [[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]] && echo yes
    

다음 명령 줄에 대한 실험은 다음과 같습니다.

if [[ `/sbin/init --version` =~ upstart ]]; then echo using upstart;
Elif [[ `systemctl` =~ -\.mount ]]; then echo using systemd;
Elif [[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]]; then echo using sysv-init;
else echo cannot tell; fi

eC2 인스턴스 (미국 동부 AMI ID 포함) :

  • ArchLinux : systemd 사용 ( 2012.10.06 부터)
  • CentOS6.4 AMI-52009e3b : 가동 시작
  • CentOS7 AMI-96a818fe : systemd 사용
  • 데비안 6 AMI-80e915e9 : sysv-init 사용
  • 데비안 7.5 AMI-2c886c44 : sysv-init 사용
  • 데비안 7.6 GCE 컨테이너 -VM : sysv-init 사용
  • RHEL 6.5 AMI-8d756fe4 : 시작 사용
  • SLES 11 AMI-e8084981 : sysv-init 사용
  • 우분투 10.04 AMI-6b350a02 : 시작 사용
  • 우분투 12.04 AMI-b08b6cd8 : 시작 사용
  • 우분투 14.04 AMI-A427EFCC : 시작 사용
  • 우분투 14.10 이하 : systemd 사용
  • AWS Linux 2014.3.2 AMI-7c807d14 : 시작 사용
  • Fedora 19 AMI-f525389c : systemd 사용
  • Fedora 20 AMI-21362b48 : 시스템 사용

분명히하기 위해 : 이것이 바보라고 주장하지는 않습니다! , 거의 확실하지 않습니다. 또한 편의상 bash regexp 일치를 사용하지만 모든 곳에서 사용할 수는 없습니다. 위의 내용은 지금 당장 충분합니다. 그러나 실패한 배포판을 찾으면 알려주십시오. 문제를 재현하는 EC2 AMI가 있으면 수정하려고합니다 ...

61
TvE

프로세스 사용

ps & systemd의 다양한 버전을 감지 할 수있는 몇 가지 upstart 명령의 출력을 살펴보면 다음과 같이 제작할 수 있습니다.

시동

$ ps -eaf|grep '[u]pstart'
root       492     1  0 Jan02 ?        00:00:00 upstart-udev-bridge --daemon
root      1027     1  0 Jan02 ?        00:00:00 upstart-socket-bridge --daemon

systemd

$ ps -eaf|grep '[s]ystemd'
root         1     0  0 07:27 ?        00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
root       343     1  0 07:28 ?        00:00:03 /usr/lib/systemd/systemd-journald
root       367     1  0 07:28 ?        00:00:00 /usr/lib/systemd/systemd-udevd
root       607     1  0 07:28 ?        00:00:00 /usr/lib/systemd/systemd-logind
dbus       615     1  0 07:28 ?        00:00:13 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation

PID # 1 인 프로세스 이름에주의를 기울이면 init 시스템이 사용되고있는 프로세스를 잠재적으로 밝힐 수 있습니다. Fedora 19 (예 : systemd 사용) :

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 07:27 ?        00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20

init이 아닙니다. Upstart를 사용하는 Ubuntu에서는 여전히 /sbin/init입니다.

$ ps -efa|grep init
root         1     0  0 Jan02 ?        00:00:03 /sbin/init

NOTE :하지만 약간주의해서 사용하십시오. 주어진 distro has에서 PID # 1로 systemd을 갖는 특정 init 시스템을 사용한다고 말하는 것은 아무것도 없습니다.

일반

$ (ps -eo "ppid,args" 2>/dev/null || echo "ps call error") \
    | awk 'NR==1 || $1==1' | less
 PPID   COMMAND
    1   /lib/systemd/systemd-journald
    1   /lib/systemd/systemd-udevd
    1   /lib/systemd/systemd-timesyncd

Ppid 1 (init 프로세스의 자식)이있는 프로세스를보십시오. 하위 프로세스 이름 중 일부는 사용중인 init 시스템을 가리킬 수 있습니다.

파일 시스템

init 실행 파일을 조사하면 해당 정보도 얻을 수 있습니다. --version 출력을 파싱하면됩니다. 예를 들면 다음과 같습니다.

시동

$ Sudo /sbin/init --version
init (upstart 1.5)
Copyright (C) 2012 Scott James Remnant, Canonical Ltd.

This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

systemd

$ type init
init is /usr/sbin/init

NOTE :init이 (가) 표준 위치에 있지 않다는 사실은 약간의 힌트/말입니다. 항상 sysvinit 시스템의 /sbin/init에 있습니다.

sysvinit

$ type init
init is /sbin/init

또한 이것 :

$ Sudo init --version
init: invalid option -- -
Usage: init 0123456SsQqAaBbCcUu

결론

따라서 한 가지 방법이없는 것처럼 보이지만 사용중인 init 시스템을 정확하게 파악할 수있는 일련의 검사를 공식화 할 수 있습니다.

19
slm

그렇게 효율적이지는 않지만 작동하는 것 같습니다.

strings /sbin/init | grep -q "/lib/systemd" && echo SYSTEMD
strings /sbin/init | grep -q "sysvinit" && echo SYSVINIT
strings /sbin/init | grep -q "upstart" && echo UPSTART

둘 이상의 문자열이 일치하면 더 많은 행을 인쇄하여 "추측 할 수 없음"으로 변환 될 수 있습니다. grep에 사용되는 문자열은 약간 수정 될 수 있지만 다음 os에서 테스트 할 때 항상 한 줄을 얻었습니다.

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (Nahant 업데이트 7) [SYSVINIT]
  • 우분투 16.04.1 LTS [SYSTEMD]
  • 우분투 14.04.2 LTS [UPSTART]
  • Fedora 릴리스 23 (온라인 셸) [SYSTEMD]
  • 데비안 GNU/리눅스 7 (온라인 셸) [SYSTEMD]
  • Centos 7.6 (VM) [SYSTEMD]

동일한 솔루션에 대한보다 단순한 접근 방식 (그러나 첫 번째 일치시 중지)

strings /sbin/init |
  awk 'match($0, /(upstart|systemd|sysvinit)/) { print toupper(substr($0, RSTART, RLENGTH));exit; }'
15
Marinos An

때때로 ls를 사용하는 것만 큼 쉽습니다 :

$ ls -l /sbin/init
lrwxrwxrwx 1 root root 20 juin  25 12:04 /sbin/init -> /lib/systemd/systemd

/sbin/init은 (는) 심볼릭 링크가 아닙니다. 다른 답변에서 다음 제안을 추가로 확인해야합니다.

10

나도 같은 문제가 있었고 일부 RedHat/CentOS/Debian/Ubuntu/Mint 컴퓨터에서 많은 테스트를 수행했습니다. 이것은 내가 끝내서 좋은 결과를 얻었습니다.

  1. PID 1로 실행 파일 이름을 찾으십시오.

    ps -p 1
    

    시스템 또는 시동 상태이면 문제가 해결 된 것입니다. "init"인 경우 심볼릭 링크이거나 이름이 아닌 다른 이름 일 수 있습니다. 어서.

  2. 실행 파일의 실제 경로를 찾으십시오 (루트로만 작동).

    ls -l `which init`
    

    init가 Upstart 또는 systemd에 대한 심볼릭 링크 인 경우 문제가 해결되었습니다. 그렇지 않으면 거의 SysV 초기화가 확실합니다. 그러나 이름이 잘못 지정된 실행 파일 일 수 있습니다. 어서.

  3. 실행 파일을 제공하는 패키지를 찾으십시오. 불행히도 이것은 배포판에 따라 다릅니다.

    dpkg-query -S (executable real path) # Debian  
    rpm -qf (executable real path) # RedHat  
    

그런 다음 스크립트를 작성하려면 (가장 재미있는 부분, IMHO), 이들은 내 단일 라이너입니다 (루트로 실행).

ls -l $(which $(ps -p 1 o comm)) | awk '{ system("dpkg-query -S "$NF) }' # Debian  

ls -l $(which $(ps -p 1 o comm)) | awk '{ system("rpm -qf "$NF) }' # RedHat  
5
Emerson Prado
  1. 이것이 배포판 전용 패키지입니다. init 시스템을 감지하는 것보다 소프트웨어를 올바르게 설치하는 것이 훨씬 더 많습니다. 많은 배포판에서 SysVinit를 사용하지만 모두 동일한 방식으로 초기화 스크립트를 작성하는 것은 아닙니다. 이 문제를 해결하는 올바른 방법은 모든 다른 변형을 포함시킨 다음 rpm 배포판의 배포 판별 종속성 이름이있는 사양 파일, apt 기반 시스템의 deb 파일 등을 사용하여 묶는 것입니다. 거의 모든 배포판에는 일종의 패키지 사양이 있습니다. 의존성, 스크립트, 초기화 스크립트 등을 포함하는 글을 쓸 수 있습니다. 여기서 바퀴를 다시 발명하지 마십시오.

  2. 아니요. 어느 것이 우리를 1로 다시 가져옵니다. bash가 필요한 경우 종속성이 있어야합니다. 이 검사를 구성 스크립트의 일부로 지정할 수 있지만 패키지 설명에도 포함되어 있어야합니다.

Edit : 구성 스크립트에서 --with upstart 또는 --without sysvinit. 적절한 기본값을 선택하면 다른 배포판 용 소프트웨어를 패키지로 제공하는 스크립트가 다른 옵션으로이를 실행하도록 선택할 수 있습니다.

3
Caleb

또한 파일 설명자를 검사하면 도움이 될 수 있습니다. 그리고 실제로 init을 실행하는 것입니다 (Debian stretch는 현재 더 많은 init 시스템을 설치할 수 있습니다) :-)

$ ls -l /proc/1/fd |grep systemd
lrwx------ 1 root root 64 srp 14 13:56 25 -> /run/systemd/initctl/fifo
lr-x------ 1 root root 64 srp 14 13:56 6 -> /sys/fs/cgroup/systemd

$ ls -l /proc/1/fd |grep /run/initctl # sysvinit
lrwx------ 1 root root 64 srp 14 14:04 10 -> /run/initctl

$ ls -l /proc/1/fd |grep upstart
l-wx------ 1 root root 64 srp 13 16:09 13 -> /var/log/upstart/mysql.log.1 (delete
l-wx------ 1 root root 64 srp 13 16:09 9 -> /var/log/upstart/dbus.log.1 (deleted)

$ ls -l /proc/1/fd # busybox
total 0
lrwx------    1 root     root          64 Jan  1 00:00 0 -> /dev/console
lrwx------    1 root     root          64 Jan  1 00:00 1 -> /dev/console
lrwx------    1 root     root          64 Jan  1 00:00 2 -> /dev/console

Busybox는 일반적으로 symlink를 사용하기 때문에 busybox를 확인하는보다 안전한 방법은 check /proc/1/exe입니다.

$ ls -l /proc/1/exe 
lrwxrwxrwx    1 root     root          0 Jan  1 00:00 /proc/1/exe -> /bin/busybox

따라서 확인은 다음과 같습니다.

{ ls -l /proc/1/fd |grep -q systemd && echo "init: systemd"; } || \
{ ls -l /proc/1/fd |grep -q /run/initctl && echo "init: sysvinit"; } || \
{ ls -l /proc/1/fd |grep -q upstart && echo "init: upstart"; } || \
{ ls -l /proc/1/exe |grep -q busybox && echo "init: busybox"; } || \
echo "unknown init"
3
pevik

PID 1을 사용하여 프로세스를 간단히 파악하면 다음과 같이 알 수 있습니다.

strings /proc/1/exe |grep -q sysvinit
strings /proc/1/exe |grep -q systemd
2
Cyrille Pontvieux

다른 시스템에 대해서는 Debian (wheezy)/or Ubuntu (14.10.)에 대해 모르지만 일반 file 명령으로 이러한 문제를 테스트합니다.

file /sbin/init

이것을주세요 :

/sbin/init: symbolic link to 'upstart'

systemd (예 : sid)가있는 데비안 시스템은 다음을 보여줍니다.

# file /sbin/init 
/sbin/init: symbolic link to /lib/systemd/systemd
2
zzeroo

데비안에서/sbin/init는 기본 init에 대한 심볼릭 링크이므로

ls -l /sbin/init

찾고있는 정보를 제공합니다.

$ ls -l /sbin/init 
lrwxrwxrwx 1 root root 20 nov 18 13:15 /sbin/init -> /lib/systemd/systemd
2
rmorelli74

젠투에서는 pid 1을 살펴보십시오.

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   4216   340 ?        Ss    2013   0:57 init [3]

init이면 초기화 시스템은 OpenRC입니다. systemd이면 초기화 시스템은 systemd입니다.

[ -f /etc/gentoo-release ].

젠투의 또 다른 방법은 profile-config show, 사용중인 기본 프로필이 표시됩니다./systemd로 끝나는 두 개를 제외한 모든 프로필은 OpenRC init를 사용합니다. 이는 기본값을 나타내는 것일 뿐이며 사용자가 해당 기본값을 재정의하는 단계를 수행했으며 실제로 사용중인 초기화 관리자를 나타내지 않을 수도 있습니다.

2
casey

이것은 일부 init 시스템에서 정말 쉽습니다. systemd의 경우 :

test -d /run/systemd/system

시동을 위해 :

initctl --version | grep -q upstart

그 밖의 다른 것이라면, 배포판 (OS X에서 시작, 데비안에서 sysvinit, 젠투에서 OpenRC)을 기반으로 가정 할 수 있습니다.

1
CameronNemo

systemd의 경우 :

if [[ `systemctl is-system-running` =~ running ]]; then echo using systemd; fi
1
guilhermebr

내 솔루션 : ID 1의 프로세스로 실행중인 명령을 확인하십시오.

case `cat /proc/1/comm` in
    init)    echo Init ;;
    systemd) echo SystemD ;;
    # add here other patterns
    *)       echo "unknown: '`cat /proc/1/comm`'" ;;
esac

현재 Init 및 SystemD 시스템에만 액세스 할 수 있으므로 Upstart 또는 macOS (OS X)가 어떻게 감지되는지 알 수 없지만 계속 검색하겠습니다.

1
t0r0X

감지를 수행하는 bash 스크립트는 다음과 같습니다. 현재 시동 및 시스템 검사 만 수행하지만 확장하기 쉬워야합니다. 나는 이것을 DisplayLink 드라이버 설치 스크립트에 기여한 코드에서 를 취했다.

detect_distro()
{
  # init process is pid 1
  INIT=`ls -l /proc/1/exe`
  if [[ $INIT == *"upstart"* ]]; then
    SYSTEMINITDAEMON=upstart
  Elif [[ $INIT == *"systemd"* ]]; then
    SYSTEMINITDAEMON=systemd
  Elif [[ $INIT == *"/sbin/init"* ]]; then
    INIT=`/sbin/init --version`
    if [[ $INIT == *"upstart"* ]]; then
      SYSTEMINITDAEMON=upstart
    Elif [[ $INIT == *"systemd"* ]]; then
      SYSTEMINITDAEMON=systemd
    fi
  fi

  if [ -z "$SYSTEMINITDAEMON" ]; then
    echo "WARNING: Unknown distribution, assuming defaults - this may fail." >&2
  else
    echo "Init system discovered: $SYSTEMINITDAEMON"
  fi
}
1
Ben McCann

Systemd와 initd를 테스트 할 때 호환성 문제가 많이 있습니다. 이것은 실제로 OpenSuSE 42.1에서 작동합니다. ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'

1
David Lakatos

이거 어때?

strings $(\ps -p 1 o cmd= | cut -d" " -f1) | egrep -o "upstart|sysvinit|systemd" | head -1

내가 가진 시스템에서만 테스트했습니다 : Ubuntu 및 SailfishOS.

0
SebMa
check(){
    if hash systemctl 2>/dev/null;
    then
        echo "there is systemd"
    fi

    if hash initctl 2>/dev/null;
    then
        echo "there is upStart"
    fi

    if [ -f "/etc/inittab"];
    then
        echo "there is systemV"
    fi
}
0
hxysayhi