bash: algún problema al usar leer <<< "$ VARIABLE" en una partición raíz de solo lectura. ¿Alguna solución conocida?

11

Solo por coincidencia tuve que usar mi script ATA-ID-to-device-name (que se encuentra aquí: /server/244944/linux-ata-errors-translating-to-a-device-name/ 426561 # 426561 ) en una partición de solo lectura / . En caso de que tenga curiosidad, era una consola de recuperación de Ubuntu que le permitirá acceder a su /partición, pero la montará de solo lectura de forma predeterminada. Me alegro de eso, porque de lo contrario, probablemente nunca habría descubierto que mi script se comporta de manera extraña en un sistema R / O debido a una línea específica, esta:

IFS=: read HostMain HostMid HostSub <<< "$HostFull"

Esto no funciona si no hay permiso de escritura. Sin embargo, no habría asumido que fallaría. Pero al parecer, el <<<operador no necesita escribir algún archivo temporal a alguna parte.

Pero, ¿hay alguna forma de eludir la creación de un archivo temporal o hay alguna forma de especificar dónde se escribe el archivo? En la consola de recuperación de Ubuntu, hay --- curiosamente --- permiso de escritura en el /rundirectorio, por lo que sería suficiente si pudiera de alguna manera "decirle" readque escriba el archivo temporal en otro lugar de lo habitual.

error de sintaxis
fuente
2
@gniourf_gniourf No, "abrir un descriptor de archivo" no sería un problema (¿por qué lo haría?), y /dev/fdno tiene nada que ver con esto. <<<Sin embargo, es el culpable, porque crea un archivo temporal (que debe escribirse en alguna parte).
Gilles 'SO- deja de ser malvado'

Respuestas:

8

Una matriz podría hacer el análisis de la cadena sin la necesidad de un archivo temporal. No te olvides de desactivar el engorde.

set -f
IFS=: Hosts=($HostFull)
HostMain=${Hosts[0]}
HostMid=${Hosts[1]}
HostSub=${Hosts[2]}
set +f
xae
fuente
2
o incluso sin IFS, si está seguro de que no hay espacios en $HostFullque así: Hosts=( ${HostFull//:/ } ). O incluso si hay espacios: HostMain=${HostFull%%:*}; HostMid=${HostFull#*:}; HostSub=${HostMid#*:}; HostMid=${HostMid%:*}(o algo similar, me estoy confundiendo :D).
gniourf_gniourf
Tiene razón, ya que muestra que la expansión de parámetros es un
asunto
4

Estoy de acuerdo con @gniourf_gniourf, probablemente necesites acceso de escritura pero no a los descriptores de archivo, probablemente un archivo.

Puede probar esto rastreando la ejecución de su comando cuando está en la partición de solo lectura.

{ strace -p "$$" & sleep 1; read var1 <<< "hi"; sleep 1; kill "$1"; }

Lo anterior se ejecutará straceen el shell Bash (proceso $$). Luego duerme durante 1 segundo y luego ejecuta readel AQUÍ de la CADENA. He puesto la cuerda "hi"en esta posición. Luego sleeppor un segundo más y luego killel strace.

Ejemplo

Al analizar esta salida, notará que un archivo se abre como O_WRONLY, que es para escribir en un archivo.

open("/tmp/sh-thd-4137571604", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3

Arriba podemos ver en qué archivo está siendo escrito por su secuencia de comandos.

slm
fuente
1
No para "crear los descriptores de archivo" (eso no tiene ningún sentido). Para crear el archivo . No es readque abra un archivo para escribir (eso sería una tontería), es <<<.
Gilles 'SO- deja de ser malvado'
@Gilles: gracias, no entendí lo que me decía. Limpié la A.
slm
¡Muchas gracias! Una técnica muy buena, que incluso podría ayudarme varias veces en el futuro con problemas similares. Sin embargo, una cosa es que me preocupa, y que es el hecho de que /tmpes un codificado camino. Y probablemente lo hayas adivinado, ya /tmp está allí, ¡pero también de solo lectura! Y dado que trabajar en esa consola de recuperación me hará iniciar sesión en mi sistema de archivos en vivo , no me gustaría meterme allí simpatizando o lo que sea (ni siquiera mientras esté en esa consola).
syntaxerror
3

Encuentro parámetros posicionales muy útiles para este tipo de tarea. Por lo general, también es portátil para todos los shells y no cuesta tenedores ni archivos temporales.

$ HostFull=main:mid:sub    
$ oldIFS=$IFS; IFS=:; set -- $HostFull; IFS=$oldIFS
$ echo $1
main
$ echo $2
mid
$ echo $3
sub
David Sainty
fuente
Un buen enfoque! Gracias. Además, me gusta que no requiera ninguna herramienta externa (que normalmente no se espera que encontremos en esos entornos restringidos). La única cosa que puede causar algunos problemas es el $1, $2, $3cosas: recordar que en una secuencia de comandos, lo cual suele reposar por un argumento pasado a la secuencia de comandos en sí . - Y mientras estamos en eso: si IFS está destinado a ser un espacio, * IFS = * no funcionará en esta sintaxis; Tendrá que especificar IFS = '' explícitamente.
syntaxerror