it-swarm-tr.com

Başlangıç ​​sistemini kabuk kullanarak algılama

Bu, işletim sistemlerinin algılanmasıyla ilgili olabilir, ancak özellikle şu anda sistemde kullanılan init sistemine ihtiyacım var.

Fedora 15 ve Ubuntu artık systemd kullanıyor, Ubuntu Upstart kullanıyor (15.04'e kadar uzun süre varsayılan), diğerleri ise Sistem V varyasyonlarını kullanıyor.

Bir platformlar arası daemon olmak için yazdığım bir uygulamam var. İnit komut dosyaları, configure betiğinde geçirilebilen parametrelere dayalı olarak dinamik olarak oluşturulmaktadır.

Ne yapmak istiyorum sadece kullandıkları belirli init sistemi için komut dosyası oluşturmaktır. Bu şekilde yükleme betiği root olarak parametreler olmadan makul bir şekilde çalıştırılabilir ve arka plan programı otomatik olarak "kurulabilir".

Ben geldim budur:

  • / Bin içinde systemd, uptart, vb.
  • / Proc/1/comm ile systemd, upstart, vs'yi karşılaştırın
  • Kullanıcıya sor

Bunu yapmanın en iyi çapraz/platform yolu nedir?

İlgili bir tür, * nix'in çoğunluğuna bash bağımlı olabilir miyim, yoksa dağıtım/işletim sistemine bağımlı mı?

Hedeflenen platformlar:

  • Mac os işletim sistemi
  • Linux (tüm dağıtımlar)
  • BSD (tüm sürümler)
  • Solaris, Minix ve diğer * nix
96
beatgammit

İkinci soru için cevap hayır ve Taşınabilir Shell programlama kaynakları .

İlk bölüme gelince - her şeyden önce, kesinlikle dikkatli olmalısınız. Ben emin olmak için birkaç test yapmak - çünkü biri var systemd (ex.) Yüklü olması, aslında olduğu anlamına gelmez varsayılan init olarak kullanılır. Ayrıca, /proc/1/comm yanıltıcı olabilir, çünkü çeşitli init programlarının bazı kurulumları otomatik olarak /sbin/init bir symlink hardlink veya hatta ana programlarının yeniden adlandırılmış bir sürümü.

Belki de en faydalı şey, init betikleri türüne bakmak olabilir - çünkü bunlar, ne çalıştırırsa çalıştırsın, gerçekte yaratacağınız şeydir.

Bir yan not olarak, hem Linux hem de BSD sistemleriyle uyumlu bir init komut dosyası yapısı sağlamayı amaçlayan OpenRC konusuna da göz atabilirsiniz.

30
rozcietrzewiacz

Bu soruna kendim adım attım ve bazı testler yapmaya karar verdim. Her dağıtım için ayrı ayrı paketlenmesi gerektiği cevabına tamamen katılıyorum, ancak bazen bunu önleyen pratik konular var (en az insan gücü değil).

Bu yüzden "otomatik algılamak" isteyenler için sınırlı bir dağıtım setinde (daha fazlası):

  • Start-up'ı şu adresten söyleyebilirsiniz:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
    
  • Systemd'yi aşağıdakilerden anlayabilirsiniz:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
    
  • Sys-v init'i şu adresten söyleyebilirsiniz:

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

İşte aşağıdaki komut satırı ile deneylerim:

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 bulut sunucularında (abd-doğu AMI kimliğini dahil ediyorum):

  • ArchLinux: systemd kullanıyor ( 2012.10.06 tarihinden beri)
  • CentOS6.4 AMI-52009e3b: upstart kullanma
  • CentOS7 AMI-96a818fe: systemd kullanma
  • Debian 6 AMI-80e915e9: sysv-init kullanma
  • Debian 7.5 AMI-2c886c44: sysv-init kullanma
  • Debian 7.6 GCE container-vm: sysv-init kullanma
  • RHEL 6.5 AMI-8d756fe4: upstart kullanma
  • SLES 11 AMI-e8084981: sysv-init kullanma
  • Ubuntu 10.04 AMI-6b350a02: upstart kullanma
  • Ubuntu 12.04 AMI-b08b6cd8: upstart kullanma
  • Ubuntu 14.04 AMI-a427efcc: upstart kullanma
  • Ubuntu 14.10 ve daha genç: systemd kullanma
  • AWS linux 2014.3.2 AMI-7c807d14: upstart kullanma
  • Fedora 19 AMI-f525389c: systemd kullanma
  • Fedora 20 AMI-21362b48: systemd kullanma

Açık olmak gerekirse: Bunun kusursuz olduğunu iddia etmiyorum! , neredeyse kesinlikle değil. Ayrıca, kolaylık sağlamak için her yerde bulunmayan bash regexp maçlarını kullandığımı unutmayın. Yukarıdakiler benim için yeterince iyi. Ancak, başarısız olduğu bir dağıtım bulursanız, lütfen bana bildirin, sorunu yeniden üreten bir EC2 AMI varsa düzeltmeye çalışacağım ...

61
TvE

Süreçleri kullanma

Çıktıya, ps & systemd'ın çeşitli sürümlerini algılayabilen birkaç upstart komutundan bakın:

sonradan görme

$ 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 işleminin adına dikkat etmek, init sisteminin kullanıldığı potansiyel olarak da ışık tutabilir. Fedora 19'da (systemd kullanan, örneğin:

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

Dikkat edin init. Upstart ile Ubuntu'da hala /sbin/init.

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

NOT: Ancak bunu biraz dikkatli kullanın. Belirli bir dağıtım sisteminde kullanılan belirli bir başlangıç ​​sisteminin PID olarak systemd değerine sahip olduğunu söyleyen herhangi bir taş yoktur. # 1.

jenerik

$ (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 sürecinin çocukları) ile süreçlere bakın. Alt işlem adlarının (bazıları), kullanılan init sistemine işaret edebilir.

Dosya sistemi

init yürütülebilir dosyasını sorgularsanız, ondan da bazı bilgiler alabilirsiniz. Basitçe --version çıktı. Örneğin:

sonradan görme

$ 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

NOT:init 'in standart konumunda olmaması biraz ipucu/söyle. Her zaman /sbin/init sysvinit sistemlerinde.

sysvinit

$ type init
init is /sbin/init

Ayrıca bu:

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

Sonuçlar

Yani bunu yapmanın tek bir yolu yok gibi görünüyor, ama hangi init sistemini kullandığınızı oldukça yüksek bir güvenle belirleyecek bir dizi kontrol formüle edebilirsiniz.

19
slm

O kadar verimli değil ama işe yarıyor gibi görünüyor.

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

Birden fazla dize eşleşirse "Tahmin edilemiyor" olarak çevrilebilecek daha fazla satır yazdırır. Grep'te kullanılan teller biraz değiştirilebilir, ancak aşağıdaki işletim sisteminde test edildiğinde her zaman bir satır aldım.

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (Nahant Güncellemesi 7) [SYSVINIT]
  • Ubuntu 16.04.1 LTS [SYSTEMD]
  • Ubuntu 14.04.2 LTS [UPSTART]
  • Fedora sürüm 23 (çevrimiçi Shell) [SYSTEMD]
  • Debian GNU/Linux 7 (çevrimiçi Kabuk) [SYSTEMD]
  • Centos 7.6 (VM) [SYSTEMD]

Aynı çözümün daha basit bir yaklaşımı (ancak ilk maçta durur)

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

Bazen ls kullanmak kadar kolaydır:

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

Sanırım /sbin/init sembolik bir bağlantı değildir, diğer yanıtlarda aşağıdaki önerileri kontrol etmeniz gerekir.

Aynı problemi yaşadım ve bazı RedHat/CentOS/Debian/Ubuntu/Mint makinelerinde birçok test yaptım. Sonuçta iyi sonuçlarla sonuçlandım.

  1. PID 1 ile yürütülebilir dosyanın adını bulun:

    ps -p 1
    

    Systemd veya Upstart ise, sorun çözüldü. "İnit" ise, bir sembolik bağlantı veya açık bir addan başka bir şey olabilir. Devam et.

  2. Yürütülebilir dosyanın gerçek yolunu bulun (yalnızca root olarak çalışın):

    ls -l `which init`
    

    init Upstart veya systemd için bir sembolik bağlantı ise, sorun çözüldü. Aksi takdirde neredeyse SysV init'iniz olduğu kesindir. Ancak bu, yanlış adlandırılmış bir yürütülebilir dosya olabilir. Devam et.

  3. Yürütülebilir dosyayı sağlayan paketi bulun. Ne yazık ki, bu dağıtım bağımlıdır:

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

Sonra, (en komik kısmı, IMHO) komut dosyasını yazmak istiyorsanız, bunlar benim tek katmanlarım (kök olarak çalıştır):

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. Dağıtım için özel paketler budur. Yazılımı düzgün bir şekilde kurmak için, init sistemini algılamaktan çok daha fazlası vardır. Birçok dağıtım SysVinit kullanıyor, ancak hepsi init komut dosyalarını aynı şekilde yazmıyor. Bunu çözmenin uygun yolu, tüm farklı varyantları dahil etmektir ve daha sonra rpm dağıtımları için distro-spesifik bağımlılık adlarına sahip spec dosyalarını, apt tabanlı sistemler için deb dosyalarını vb. Kullanarak paketlemektir. bağımlılıkları, komut dosyalarını, başlangıç ​​komut dosyalarını vb. içeren bir yazı yazabilir. Burada tekerleği yeniden icat etmeyin.

  2. Hayır. Bu bizi 1'e geri getiriyor. Eğer bash'a ihtiyacınız varsa bir bağımlılık olmalı. Bu denetimi yapılandırma komut dosyalarınızın bir parçası olarak belirtebilirsiniz, ancak paket açıklamalarında da olması gerekir.

Edit: Yapılandırma komut dosyanızda --with upstart veya --without sysvinit. Aklı başında bir varsayılan seçin, ardından yazılımınızı diğer dağıtımlar için paketleyen komut dosyaları bunu diğer seçeneklerle çalıştırmayı seçebilir.

3
Caleb

Ayrıca dosya tanımlayıcıları incelemek de yardımcı olabilir. Ve aslında init çalıştırmaktan (Debian streç şu anda daha fazla init sisteminin kurulmasına izin veriyor) :-)

$ 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

Meşgul kutusunu kontrol etmenin muhtemelen daha güvenli bir yolu check /proc/1/exe, busybox genellikle sembolik bağlantılar kullandığından:

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

Yani kontrol şöyle olabilir:

{ 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 ile sürece girmeniz size şunları söyleyecektir:

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

Sonra Debian (wheezy)/veya Ubuntu (14.10.) Diğer sistemleri bilmiyorum ama düz eski file komutuyla bu tür sorunları test ediyorum.

file /sbin/init

bunu ver:

/sbin/init: symbolic link to 'upstart'

systemd (örneğin sid) bulunan Debian sistemleri bunu gösterir:

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

Debian/sbin/init üzerinde varsayılan başlangıcınızın bağlantısı

ls -l /sbin/init

aradığınız bilgiyi size verecektir.

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

Gentoo'da pid 1'e bir göz atın:

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 ise, başlatma sistemi OpenRC olur. systemd ise, başlatma sistemi systemd olur.

Gentoo'yu [ -f /etc/gentoo-release ].

Gentoo üzerinde başka bir yöntem profile-config show, hangi varsayılan profilin kullanıldığını gösterir./Systemd ile biten iki profil dışındaki tüm profiller OpenRC başlığını kullanır. Bunların yalnızca bir varsayılanı temsil ettiğini ve kullanıcının bu varsayılanı geçersiz kılmak için adımlar atmış olabileceğini ve aslında kullanımda olan başlangıç ​​yöneticisinin göstergesi olmayabileceğini unutmayın.

2
casey

Bazı init sistemleri için bu gerçekten kolaydır. Systemd için:

test -d /run/systemd/system

uptart için:

initctl --version | grep -q upstart

başka herhangi bir şey için, sadece dağıtıma (OS X'te başlatılır, Debian'da sisvinit, Gentoo'da OpenRC) dayanabilir.

1
CameronNemo

systemd için:

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

Benim çözümüm: ID 1 ile işlem olarak çalışan komutu kontrol edin.

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

Şu anda yalnızca Init ve SystemD makinelerine erişimim var, bu yüzden Upstart veya macOS'un (OS X) nasıl tespit edileceğini söyleyemem, ancak aramaya devam edeceğim.

1
t0r0X

Algılamayı yapmak için bir bash betiği. Sadece şu anda uptart ve systemd'yi kontrol eder, ancak uzatılması kolay olmalıdır. Bunu aldım koddan DisplayLink sürücü yükleme komut dosyasına katkıda bulundum .

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 ve initd'yi test ederken birçok uyumluluk sorunu var. Bu aslında OpenSuSE 42.1'de çalışıyor: ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'

1
David Lakatos

Buna ne dersin:

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

Sadece sahip olduğum sistemlerde test edildi: Ubuntu ve 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