En algunos Bourne como conchas, la readorden interna no puede leer toda la línea del archivo en /proc(el siguiente comando debe ser ejecutado en zsh, sustituir $=shellcon $shellotras conchas):
$ for shell in bash dash ksh mksh yash zsh schily-sh heirloom-sh "busybox sh"; do
  printf '[%s]\n' "$shell"
  $=shell -c 'IFS= read x </proc/sys/fs/file-max; echo "$x"'       
done
[bash]
602160
[dash]
6
[ksh]
602160
[mksh]
6
[yash]
6
[zsh]
6
[schily-sh]
602160
[heirloom-sh]
602160
[busybox sh]
6readEl estándar requiere que la entrada estándar deba ser un archivo de texto , ¿ese requisito causa comportamientos variados?
Lea la definición POSIX del archivo de texto , hago algunas verificaciones:
$ od -t a </proc/sys/fs/file-max 
0000000   6   0   2   1   6   0  nl
0000007
$ find /proc/sys/fs -type f -name 'file-max'
/proc/sys/fs/file-maxNo hay NULcarácter en el contenido de /proc/sys/fs/file-max, y también lo findinformó como un archivo normal (¿Es esto un error find?).
Supongo que el caparazón hizo algo debajo del capó, como file:
$ file /proc/sys/fs/file-max
/proc/sys/fs/file-max: empty
straceexplicación basada en datos es mucho más fácil de entender!cat /proc/sys/fs/file-max | ..., el problema se ha ido.procfsno puede manejar múltiplesread(2)llamadas sucesivas al mismo archivo; El comportamiento no depende del shell. El usocaty la tubería funciona porquecatlee el archivo en fragmentos lo suficientemente grandes; el shellreadincorporado luego lee de la tubería un carácter a la vez.mksh.read -N 10 a < /proc/sys/fs/file-maxzsh:read -u0 -k10(o usosysread;$mapfile[/proc/sys/fs/file-max]no funciona ya que esos archivos no se puedenmmapeditar). En cualquier caso, con cualquier shell, siempre se puedea=$(cat /proc/sys/fs/file-max). Algunos incluyenmksh,zshyksh93,a=$(</proc/sys/fs/file-max)también funciona y no bifurca un proceso para hacer la lectura.Si estás interesado en saber por qué? Esto es así, puede ver la respuesta en las fuentes del núcleo aquí :
Básicamente, la búsqueda (
*pposno 0) no se implementa para lecturas (!write) de valores sysctl que son números. Cada vez que se realiza una lectura/proc/sys/fs/file-max, la rutina en cuestión__do_proc_doulongvec_minmax()se llama desde la entrada defile-maxla tabla de configuración en el mismo archivo.Otras entradas, como las que
/proc/sys/kernel/poweroff_cmdse implementan a través de lasproc_dostring()cuales permiten búsquedas, para que pueda hacerlodd bs=1y leer desde su shell sin problemas.Tenga en cuenta que desde el kernel 2.6 la mayoría de las
/proclecturas se implementaron a través de una nueva API llamada seq_file y esto admite búsquedas, por ejemplo, la lectura/proc/statno debería causar problemas. La/proc/sys/implementación, como podemos ver, no utiliza esta API.fuente
En el primer intento, esto parece un error en los shells que devuelven menos que un Bourne Shell real o sus derivados (sh, bosh, ksh, reliquia).
El Bourne Shell original intenta leer un bloque (64 bytes). Las variantes más recientes del Bourne Shell leen 128 bytes, pero comienzan a leer nuevamente si no hay un nuevo carácter de línea.
Antecedentes: / procfs e implementaciones similares (por ejemplo, el
/etc/mtabarchivo virtual montado ) tienen contenido dinámico y unastat()llamada no causa la recreación del contenido dinámico primero. Por esta razón, el tamaño de dicho archivo (desde la lectura hasta el EOF) puede diferir de lo questat()devuelve.Dado que el estándar POSIX requiere que las empresas de servicios públicos esperen lecturas cortas en cualquier momento, el software que cree que un valor
read()que devuelve menos que la cantidad ordenada de bytes es una indicación EOF está roto. Una utilidad implementada correctamente llamaread()por segunda vez en caso de que devuelva menos de lo esperado, hasta que se devuelva un 0. En el caso de lareadconstrucción, por supuesto, sería suficiente leer hastaEOFo hasta queNLse vea un.Si corres
trusso haces un clon de truss, deberías poder verificar ese comportamiento incorrecto para los shells que solo regresan6en tu experimento.En este caso especial, parece ser un error del kernel de Linux, vea:
El kernel de Linux devuelve 0 con el segundo
ready, por supuesto, esto es incorrecto.Conclusión: los shells que primero intentan leer una porción de datos lo suficientemente grande no activan este error del kernel de Linux.
fuente
Los archivos bajo / proc a veces usan caracteres NULL para separar los campos dentro del archivo. Parece que leer no puede manejar esto.
fuente