¿Qué tan estables son las "API stdin/stdout" del shell Unix?

¿Qué tan estables son las "API stdin/stdout" del shell Unix?

grepping, awking, sedding y piping son rutinas diarias de un usuario de cualquier sistema operativo tipo Unix, ya sea en la línea de comando o dentro de un script de shell (colectivamente llamadofiltrosde aquí en adelante).

En esencia, cuando se trabaja con programas CLI de Unix "estándar" y funciones integradas de shell (llamadas colectivamentecomandosde ahora en adelante), los filtros necesitan un formato esperado preciso para stdin, stdout y stderr en cada paso del filtro para poder funcionar correctamente. A este formato esperado preciso de algún comando lo llamo API de este comando a continuación.

Como alguien con experiencia en desarrollo web, comparo técnicamente este tipo de recopilación y procesamiento de datos conraspado web- una técnica que es muy inestable ante el más mínimo cambio en la presentación de los datos.

Mi pregunta ahora se relaciona con la estabilidad de las API de comandos de Unix.

  1. ¿Los comandos en sistemas operativos tipo Unix se adhieren a una estandarización formal con respecto a su entrada y salida?
  2. ¿Ha habido casos en la historia en los que las actualizaciones de algún comando importante provocaron que se rompiera la funcionalidad de algún filtro que se creó con una versión anterior de dicho comando?
  3. ¿Los comandos de Unix han madurado con el tiempo y es absolutamente imposible cambiarlos de tal manera que algún filtro pueda romperse?
  4. En caso de que los filtros puedan fallar de vez en cuando debido al cambio de las API de comando, ¿cómo puedo yo, como desarrollador, proteger mis filtros contra este problema?

Respuesta1

El estándar POSIX 2008 tiene una sección que describe"Shell y utilidades". En general, si se apega a eso, sus scripts deberían estar bastante preparados para el futuro, excepto posiblemente por las desaprobaciones, pero estas rara vez ocurren de la noche a la mañana, por lo que debería tener suficiente tiempo para actualizar sus scripts.

En algunos casos donde el formato de salida para una sola utilidad varía ampliamente entre plataformas y versiones, el estándar POSIX puede incluir una opción típicamente llamada -po -Pque especifica un formato de salida garantizado y predecible. Un ejemplo de esto es eltimeutilidad, que tiene implementaciones muy diversas. Si necesita una API/formato de salida estable, usaría time -p.

Si necesita utilizar una utilidad de filtro que no está cubierta por el estándar POSIX, entonces está prácticamente a merced de los empaquetadores de distribución/desarrolladores ascendentes, del mismo modo que está a merced de los desarrolladores web remotos cuando realiza web scraping.

Respuesta2

Intentaré responder desde mi experiencia.

  1. Los comandos realmente no cumplen con una especificación formal, pero sí cumplen con el requisito de consumir y generar texto orientado a líneas.

  2. Sí, claro. Antes de que las utilidades GNU se convirtieran en un estándar de facto, muchos proveedores tenían resultados extravagantes, especialmente con respecto a psy ls. Esto causó mucho dolor. Hoy en día, sólo HP ofrece comandos súper extravagantes. Históricamente, las utilidades de Berkeley Software Distribution (BSD) supusieron una ruptura importante con el pasado. La especificación POSIX supuso una ruptura con el pasado, pero ahora es ampliamente aceptada.

  3. De hecho, los comandos de Unix han madurado con el tiempo. Todavía no es imposible romper algún script escrito para una versión anterior. Piense en la tendencia reciente hacia UTF-8 como codificación de archivos de texto. Este cambio requirió cambiar utilidades básicas como tr. En el pasado, el texto simple casi siempre era ASCII (o algo parecido), por lo que las letras mayúsculas formaban un rango numérico, al igual que las letras minúsculas. Eso ya no es cierto con UTF-8, por lo que trpuede aceptar diferentes opciones de línea de comando para especificar cosas como "mayúsculas" o "alfanuméricas".

  4. Una de las mejores formas de "reforzar" sus filtros es no depender de un diseño de texto en particular. Por ejemplo, no lo hagas cut -c10-24, que depende de las posiciones de una línea. Úselo cut -f2en su lugar, lo que eliminaría el segundo campo separado por tabulaciones. awkdivide cualquier línea de entrada en $1, $2, $3... que están separadas por espacios en blanco de forma predeterminada. Depende de conceptos de nivel superior como "campos" en lugar de conceptos de nivel inferior como la posición de la columna. Además, use expresiones regulares: sedy awkambos pueden hacer cosas con expresiones regulares que no se preocupan por alguna variación en la entrada. Otro truco consiste en procesar la entrada en algo cuyo formato su filtro pueda elegir. Úselo tr -cs '[a-zA-z0-9]' '[\n]'para dividir el texto en una sola palabra por línea, sin puntuación. En ese caso, simplemente no te importa cómo sea el texto de entrada.

Respuesta3

Primero, respuestas muy breves a sus preguntas:

  1. Estandarización formal de convenciones de entrada/salida:No
  2. Rotura en el pasado por cambio de producción:
  3. Absolutamente imposible romper filtros futuros:No
  4. ¿Cómo puedo protegerme contra los cambios?ser conservador

Cuando dices "API", estás usando un término que (para bien o para mal) implica demasiada formalidad en torno a las convenciones de entrada/salida de filtros. En términos muy generales (y quiero decir "muy"), las convenciones principales para los datos que se pueden filtrar fácilmente son

  • cada línea de entrada es un registro completo
  • dentro de cada registro, los campos están separados por un carácter delimitador conocido

Un ejemplo clásico sería el formato de /etc/passwd. Pero estas convenciones predeterminadas probablemente se violan hasta cierto punto con más frecuencia de lo que se siguen al pie de la letra.

  • Hay muchos filtros (a menudo escritos en awk o perl) que analizan formatos de entrada multilínea.
  • Hay muchos patrones de entrada (por ejemplo, /var/log/messages) donde no hay una estructura de campos bien definida y se deben utilizar técnicas más generales basadas en expresiones regulares.

Su cuarta pregunta, cómo protegerse contra las variaciones en la estructura de salida, es realmente la única sobre la que puede hacer algo.

  • Como@jw013 dijo, mira lo que dicen los estándares posix. Por supuesto, posix no especifica todos los comandos que querrás usar como fuentes de entrada.
  • Si desea que sus scripts sean portátiles, intente evitar las idiosincrasias de cualquier versión de algún comando que tenga instalado. Por ejemplo, muchas versiones GNU de comandos estándar de Unix tienen extensiones no estándar. Estos pueden resultar útiles, pero debes evitarlos si deseas la máxima portabilidad.
  • Intente aprender qué subconjuntos de argumentos de comandos y formatos de salida tienden a ser estables en todas las plataformas. Desafortunadamente, esto requiere acceso a múltiples plataformas y tiempo, porque estas diferencias no se escribirán en ninguna parte, ni siquiera de manera informal.

Al final, no puede protegerse completamente de los problemas que le preocupan y no existe un lugar único al que acudir para obtener una declaración "definitiva" de lo que debe hacer un determinado comando. Para muchos scripts de shell, especialmente aquellos escritos para uso personal o a pequeña escala, esto simplemente no es un problema.

Respuesta4

Solo existen estándares de IO de facto: espacios en blanco y salida separada por nulos.

En cuanto a la compatibilidad, normalmente volvemos a comprobar los números de versión de los filtros individuales. No es que cambien mucho, pero cuando desea utilizar una característica completamente nueva y aún desea que el script se ejecute en versiones anteriores, debe "ifdef" de alguna manera. Prácticamente no existe ningún mecanismo de informes de capacidad, salvo escribir casos de prueba manualmente.

información relacionada