Esto puede tener más que ver con la detección de sistemas operativos, pero específicamente necesito el sistema init actualmente en uso en el sistema.
Fedora 15 y Ubuntu ahora usan systemd, Ubuntu solía usar Upstart (tiempo predeterminado por defecto hasta 15.04), mientras que otros usan variaciones del Sistema V.
Tengo una aplicación que estoy escribiendo para ser un demonio multiplataforma. Los scripts de inicio se generan dinámicamente en función de los parámetros que se pueden pasar en la configuración.
Lo que me gustaría hacer es solo generar el script para el sistema de inicio particular que están utilizando. De esta manera, el script de instalación se puede ejecutar razonablemente sin parámetros como root y el demonio se puede "instalar" automáticamente.
Esto es lo que se me ocurrió:
- Busque systemd, upstart, etc. en / bin
- Compare / proc / 1 / comm con el systemd, upstart, etc.
- Pregunta al usuario
¿Cuál sería la mejor forma cruzada / plataforma de hacer esto?
Tipo de relacionado, ¿puedo depender de bash para estar en la mayoría de * nix o depende de la distribución / SO?
Plataformas objetivo:
- Mac OS
- Linux (todas las distribuciones)
- BSD (todas las versiones)
- Solaris, Minix y otros * nix
fuente
ps -p 1 -o command
(imprime la ruta a la actualinit
). En Arch Linux y Fedora (IIRC), es un enlace simbólico alsystemd
binario (probablemente igual en todos lossystemd
sistemas). Elupstart
,init --help
imprimirá información de uso, y en mi casilla,upstart
se menciona dónde dice a quién enviar un correo electrónico. En FreeBSD (sysV), esto devolverá un error. Puede haber pistas similares en otros sistemas, pero desde que hice esta pregunta, decidí crearlas para todas las plataformas y hacer paquetes separados para cada una.sudo lsof -a -p 1 -d txt
puede dar resultados aún más exactos.ps
puede imprimir un nombre arbitrario, mientras que conlsof
usted obtendrá la ruta real ejecutable. (Ver mi pregunta unix.stackexchange.com/questions/102453/… )Respuestas:
Para la segunda pregunta, la respuesta es no y debería echar un vistazo a Recursos para la programación de shell portátil .
En cuanto a la primera parte, antes que nada, ciertamente debes tener cuidado. Yo diría que realice varias pruebas para asegurarse , porque el hecho de que alguien tenga instalado systemd (por ejemplo) no significa que realmente se use como predeterminado
init
. Además, mirar/proc/1/comm
puede ser engañoso, porque algunas instalaciones de varios programas init pueden hacer automáticamente/sbin/init
un enlace simbólico o incluso una versión renombrada de su programa principal.Tal vez lo más útil podría ser mirar el tipo de scripts de inicio, porque eso es lo que realmente creará, sin importar qué los ejecute.
Como nota al margen, también puede echar un vistazo a OpenRC, que tiene como objetivo proporcionar una estructura de scripts de inicio que sea compatible con los sistemas Linux y BSD.
fuente
/etc/init
, como systemd los coloca/etc/systemd
. Si tuviera que hacer que mi script asimilara estos, podría tomar un poco de tiempo. Ah, y gracias por el enlace BTW para la programación de shell portátil./etc/rc.d/
o/etc/init.d/
). Y debe ajustar adecuadamente su programa en el momento de la instalación para utilizar la estructura que se utiliza en el sistema dado.Me metí en este problema y decidí hacer algunas pruebas. Estoy totalmente de acuerdo con la respuesta de que uno debe empaquetar para cada distribución por separado, pero a veces hay problemas prácticos que lo impiden (no menos mano de obra).
Entonces, para aquellos que quieren "autodetectarse", esto es lo que he descubierto en un conjunto limitado de distribuciones (más abajo):
Puedes decir advenedizo desde:
Puedes distinguir systemd de:
Puede distinguir sys-v init de:
Aquí están mis experimentos con la siguiente línea de comando:
en instancias ec2 (incluyo el ID de AMI de us-east):
Para ser claros: ¡no estoy afirmando que esto sea infalible! , casi seguro que no lo es. También tenga en cuenta que, por comodidad, uso bash regexp match, que no está disponible en todas partes. Lo anterior es lo suficientemente bueno para mí en este momento. Sin embargo, si encuentra una distribución donde falla, avíseme e intentaré solucionarla si hay un IAM EC2 que reproduce el problema ...
fuente
/run/systemd/system
existe.launchd
, el sistema init en macOS:[[ $(ps 1) =~ 'launchd' ]] && echo yes || echo no
probado en MacBookPro, macOS Sierra Versión 10.12if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Usando procesos
Mirando la salida de un par de
ps
comandos que pueden detectar las diversas versiones desystemd
&upstart
, que podrían ser creadas de esta manera:advenedizo
systemd
Prestar atención al nombre del proceso que es PID # 1 también puede arrojar luz sobre qué sistema de inicio se está utilizando. En Fedora 19 (que usa
systemd
, por ejemplo:Note que no lo es
init
. En Ubuntu con Upstart todavía está/sbin/init
.NOTA: Pero use esto con un poco de precaución. No hay nada escrito en piedra que dice que un sistema de inicio particular que está siendo utilizado en una distribución dada ha de tener
systemd
como el PID # 1.genérico
Mire los procesos con ppid 1 (hijos del proceso init). (Algunos de los) nombres de procesos secundarios pueden apuntar al sistema init en uso.
El sistema de archivos
Si interroga al
init
ejecutable, también puede obtener información de él. Simplemente analizando la--version
salida. Por ejemplo:advenedizo
systemd
NOTA: El hecho de que
init
no se encuentre en su ubicación estándar es un poco indirecto. Siempre se encuentra en los/sbin/init
sistemas sysvinit.sysvinit
También esto:
Conclusiones
Por lo tanto, no parece haber una sola forma de hacerlo, pero podría formular un conjunto de comprobaciones que determinarían qué sistema de inicio está utilizando con un grado bastante alto de confianza.
fuente
pgrep systemd >/dev/null && echo init system: systemd
/usr/lib/systemd/systemd
si se usa systemd, es una suposición falsa. En mi sistema, por ejemplo, PID # 1 es/sbin/init
(yo uso systemd). Es dependiente de la distribución.pgrep systemd >/dev/null && echo init system: systemd -> init system: systemd
ytype init -> init is /sbin/init
No es tan eficiente, pero parece que funciona.
Imprimirá más líneas si coinciden más de una cadena, lo que podría traducirse a "No puedo adivinar". Las cadenas utilizadas en grep podrían modificarse ligeramente, pero cuando se prueban en el siguiente sistema operativo siempre obtengo una línea.
Un enfoque más simplista de la misma solución (pero se detiene en el primer partido)
fuente
A veces es tan fácil como usar
ls
:Supongo que si
/sbin/init
no es un enlace simbólico, tendrá que consultar las siguientes sugerencias en otras respuestas.fuente
Para eso están los paquetes específicos de la distribución. Instalar el software correctamente es mucho más que simplemente detectar el sistema init. Muchas distribuciones usan SysVinit, pero no todas escriben sus scripts de inicio de la misma manera. La forma correcta de resolver esto es incluir todas las diferentes variantes y luego agruparlo usando archivos de especificaciones con nombres de dependencia específicos de la distribución para distribuciones rpm, archivos deb para sistemas basados en apt, etc. Casi todas las distribuciones tienen algún tipo de especificación de paquete que usted puede escribir que incluye dependencias, guiones, guiones de inicio, etc. No vuelva a inventar la rueda aquí.
No. Lo que nos lleva de nuevo a 1. Si necesita bash, debería ser una dependencia. Puede especificar esta verificación como parte de sus scripts de configuración, pero también debe estar en las descripciones del paquete.
Editar: use marcas en su script de configuración como
--with upstart
o--without sysvinit
. Elija un valor predeterminado sensato, luego los scripts que empaquetan su software para otras distribuciones pueden elegir ejecutar esto con otras opciones.fuente
En Gentoo, eche un vistazo a pid 1:
Si es así
init
, entonces el sistema init esOpenRC
. Si es asísystemd
, entonces el sistema init essystemd
.Puedes detectar Gentoo con
[ -f /etc/gentoo-release ]
.Otro método en Gentoo es el uso
profile-config show
, que mostrará qué perfil predeterminado está en uso. Todos los perfiles, excepto los dos que terminan en / systemd, usan el OpenRC init. Tenga en cuenta que estos son solo representativos de un valor predeterminado y es posible que el usuario haya tomado medidas para anular ese valor predeterminado y que no sea indicativo del gestor de inicio realmente en uso.fuente
p
opción (idéntica a-p
y--pid
) para seleccionar por PID. El fragmento anterior es en realidad la salida paraps u --pid 1
.En debian / sbin / init hay un enlace simbólico a su init predeterminado
te dará la información que estás buscando.
fuente
init
puedo instalar en Ubuntu 14.04?Simplemente pasar por el proceso con PID 1 le dirá:
fuente
proc
sistema de archivos ...También puede ayudar la inspección de descriptores de archivos. Y es en realidad ejecutando init (Debian stretch actualmente permite tener más sistemas init instalados) :-)
Probablemente, la forma más segura de verificar si busybox es
check /proc/1/exe
, ya que busybox generalmente usa enlaces simbólicos:Entonces el cheque podría ser:
fuente
/run/systemd/system
.No sé acerca de otros sistemas, entonces Debian (wheezy) / o Ubuntu (14.10.), Pero pruebo tales problemas con el
file
comando antiguo .da esto:
Los sistemas Debian con
systemd
(por ejemplo, sid) muestran esto:fuente
file /sbin/init /sbin/init: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, BuildID[sha1]=0x8c68a736c6a4e6fadf22d5ac9debf11e79c6bdcd, stripped
significa que usamos SYSV aquí. La salida para ubuntu se muestra en mi respuesta.file /sbin/init
"ejecutable" en todos los sistemas. También devuelve lo mismo en un CentOS 5.8, un SLES 10, un Ubuntu 8.04, básicamente en todos los sistemas que puedo tener en mis manos. Entonces, por lo que puedo decir, ni siquiera funciona para advenedizos y Ubuntu.También tuve el mismo problema e hice muchas pruebas en algunas máquinas RedHat / CentOS / Debian / Ubuntu / Mint. Esto es con lo que terminé, con buenos resultados.
Encuentre el nombre del ejecutable con PID 1:
Si es systemd o Upstart, el problema está resuelto. Si es "init", puede ser un enlace simbólico o algo más que un nombre inicial. Adelante.
Encuentre la ruta real para el ejecutable (solo funciona como root):
Si
init
es un enlace simbólico a Upstart o systemd, el problema está resuelto. De lo contrario, es casi seguro que tiene SysV init. Pero puede ser un ejecutable mal nombrado. Adelante.Encuentra el paquete que proporciona el ejecutable. Desafortunadamente, esto depende de la distribución:
Luego, si desea escribir un script que (la parte más divertida, en mi humilde opinión), estos son mis frases (ejecutado como root):
fuente
init --version
para obtener la información.Esto es realmente fácil para algunos sistemas init. Para systemd:
para advenedizo:
para cualquier otra cosa, puede asumir en función de la distribución (lanzado en OS X, sysvinit en Debian, OpenRC en Gentoo).
fuente
Aquí hay un script bash para hacer la detección. Por el momento, solo verifica el arranque y systemd, pero debería ser fácil de extender. Tomé esto del código que contribuí al script de instalación del controlador DisplayLink .
fuente
/proc
vínculos se relaciona con Linux (si está configurado adecuadamente) y uno o dos más; ciertamente, está lejos de ser universal.Hay muchas dificultades de compatibilidad al probar systemd vs initd. Esto realmente funciona en OpenSuSE 42.1:
ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'
fuente
Para
systemd
:fuente
Mi solución: verifique el comando que se ejecuta como proceso con ID 1.
Por el momento, solo tengo acceso a las máquinas Init y SystemD, por lo que no puedo decir cómo se detectarán Upstart o macOS (OS X), pero seguiré buscando.
fuente
fuente