bash: Algum problema ao usar a leitura <<< "$ VARIABLE" em uma partição raiz somente leitura. Alguma solução alternativa conhecida?

11

Por coincidência, tive que usar meu script ATA-ID-to-device-name (encontrado aqui: /server/244944/linux-ata-errors-translating-to-a-device-name/ 426561 # 426561 ) em uma partição somente leitura / . Caso você esteja curioso, era um console de recuperação do Ubuntu que permitirá acessar sua /partição, mas a montará como somente leitura por padrão. Fico feliz com isso, porque, caso contrário, provavelmente nunca teria descoberto que meu script se comporta estranhamente em um sistema de R / O devido a uma linha específica, esta:

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

Isso não funciona se não houver permissão de gravação. Eu não teria assumido que iria falhar, no entanto. Mas, aparentemente, o <<<operador não precisa para escrever um arquivo temporário para algum lugar.

Mas existe alguma maneira de burlar a criação de um arquivo temporário ou existe alguma maneira de especificar para onde o arquivo foi gravado? No console de recuperação do Ubuntu, existe --- estranhamente --- permissão de gravação no /rundiretório, o que seria suficiente , se eu pudesse, de alguma forma, "dizer" readpara gravar o arquivo temporário em outro lugar que o normal.

erro de sintaxe
fonte
2
@gniourf_gniourf Não, “abrir um descritor de arquivo” não seria um problema (por que seria?) e /dev/fdnão tem nada a ver com isso. <<<é o culpado, porque cria um arquivo temporário (que precisa ser gravado em algum lugar).
Gilles 'SO- stop be evil'

Respostas:

8

Uma matriz pode fazer a análise da string sem a necessidade de um arquivo temporal. Não se esqueça de desligar o globbing.

set -f
IFS=: Hosts=($HostFull)
HostMain=${Hosts[0]}
HostMid=${Hosts[1]}
HostSub=${Hosts[2]}
set +f
xae
fonte
2
ou mesmo sem IFS, se você estiver certo de que não existem espaços em $HostFullassim: Hosts=( ${HostFull//:/ } ). Ou mesmo se houver espaços: HostMain=${HostFull%%:*}; HostMid=${HostFull#*:}; HostSub=${HostMid#*:}; HostMid=${HostMid%:*}(ou algo semelhante, estou ficando confuso :D).
gniourf_gniourf
Você está certo, como você mostrar expansão de parâmetros é bussines complicadas ...
Xae
4

Concordo com @gniourf_gniourf, você provavelmente está precisando de acesso de gravação, mas não aos descritores de arquivos, provavelmente um arquivo.

Você pode testar isso rastreando a execução do seu comando na partição somente leitura.

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

O acima será executado straceno shell Bash (processo $$). Em seguida, ele dorme por 1 segundo e, em seguida, executa o a readpartir do HERE STRING. Eu coloquei a corda "hi"nesta posição. Eu então sleeppor mais um segundo e depois killo strace.

Exemplo

Ao analisar esta saída, você notará que um arquivo é aberto como O_WRONLY, que é para gravar em um arquivo.

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

Acima, podemos ver para que arquivo está sendo gravado sua sequência de comandos.

slm
fonte
1
Não para "criar os descritores de arquivo" (isso não faz sentido). Para criar o arquivo . Não é readque abre um arquivo para escrever (isso seria bobo), é <<<.
Gilles 'SO- stop be evil'
@ Gilles - obrigado, eu não entendi direito o que estava me dizendo. Limpou o A.
slm
Muito obrigado! Uma técnica muito boa, que pode até me ajudar várias vezes no futuro com problemas semelhantes. No entanto, uma coisa está me preocupando, e esse é o fato de /tmpser um caminho codificado . E, provavelmente, você adivinhou, /tmp é já ali, mas só de leitura também! E, como trabalhar nesse console de recuperação me fará logon no meu sistema de arquivos ao vivo , eu não gostaria de mexer lá por ligação simbólica ou o que quer que seja (nem mesmo enquanto estiver nesse console).
Syntaxerror
3

Acho parâmetros posicionais muito úteis para esse tipo de tarefa. Também é geralmente portátil para todas as conchas e não custa garfos nem arquivos temporários.

$ HostFull=main:mid:sub    
$ oldIFS=$IFS; IFS=:; set -- $HostFull; IFS=$oldIFS
$ echo $1
main
$ echo $2
mid
$ echo $3
sub
David Sainty
fonte
Uma boa abordagem! Obrigado. Além disso, gosto que ele não exija nenhuma ferramenta externa (que normalmente não se espera que encontremos nesses ambientes restritos). A única coisa que pode causar alguns problemas é a $1, $2, $3coisa: lembre-se que em um script, isso geralmente representam um argumento passado para o script em si . - E enquanto estamos nisso: se o IFS for um espaço, * IFS = * não funcionará nesta sintaxe; você precisará especificar IFS = '' explicitamente.
Syntaxerror 3/11/13