Manipulando espaços em branco no nome de um conjunto de dados do ZFS em um script de shell

1

Gostaria de tirar a saída de dois comandos -

zpool list
zfs list

e para cada conjunto encontrado:

zpool get all nameofpool

e para cada sistema de arquivos encontrado:

zfs get all nameoffilesystem

Antecedentes e ambiente

Estou fazendo alterações locais no script que é essencial para o OS X

/usr/bin/sysdiagnose

  • #!/bin/sh para iniciantes
  • sempre executado com privilégios de superusuário
  • às vezes, efetivamente sem cabeça ( acionado por um acorde de teclas ), então a saída deve ser um arquivo.

Primeira experiência

Baseado no exemplo em # 65 Remover todos os instantâneos do ZFS :

#!/bin/sh
for dataset in 'zfs list -H | cut -f 1'
do
  zfs get all $dataset
done

Isso funciona, mas não onde há um espaço no nome do conjunto de dados. Por exemplo, onde o sistema de arquivos é zhandy/Pocket Time Machine , a saída inclui:

cannot open 'zhandy/Pocket': dataset does not exist
cannot open 'Time': dataset does not exist
cannot open 'Machine': dataset does not exist

Segunda experiência

... foi baseado na primeira resposta a essa pergunta - usando IFS - e tornou o script mais parecido com o da Apple. Veja revisão 4 .

Terceira experiência

Com base na resposta aceita a essa pergunta - com IFS e aspas para "$dataset" :

#!/bin/sh
data_directory_path=~/Desktop
ECHO=/bin/echo
ZFS=/usr/sbin/zfs
ZPOOL=/usr/sbin/zpool
# If there exists a zfs binary, get some ZFS information
if [ -f "${ZFS}" ]
then
    "${ECHO}" "Recording ZFS pool version information ..."
    "${ZPOOL}" upgrade &> ${data_directory_path}/zpool\ upgrade.txt
    "${ECHO}" "    listing all ZFS pools ..."
    "${ZPOOL}" list &> ${data_directory_path}/zpool\ list.txt
    "${ECHO}" "    detailed health status and verbose data error information ..."
    "${ZPOOL}" status -v &> ${data_directory_path}/zpool\ status.txt
    "${ECHO}" "    pools that are available but not currently imported"
    "${ZPOOL}" import &> ${data_directory_path}/zpool\ import.txt
    "${ECHO}" "Recording ZFS file system version information ..."
    "${ZFS}" upgrade &> ${data_directory_path}/zfs\ upgrade.txt
    "${ECHO}" "    listing all ZFS file systems ..."
    "${ZFS}" list &> ${data_directory_path}/zfs\ list.txt
    "${ECHO}" "    all properties of each file system"
    OLD_IFS=$IFS
    IFS=$'\n'
    for dataset in 'zfs list -H | cut -f 1'
    do
        "${ZFS}" get all "$dataset" &> ${data_directory_path}/ZFS\ file\ system\ properties.txt
    done
    IFS=$OLD_IFS
    "${ECHO}" "Listing the contents of /dev/dsk"
    "${LS}" -@adel /Volumes &> ${data_directory_path}/ls-dev-dsk.txt
    "${ECHO}" "Listing the contents of /var/zfs/dsk"
    "${LS}" -@adel /Volumes &> ${data_directory_path}/ls-var-zfs-dsk.txt
fi

Entre os arquivos resultantes, ZFS file system properties.txt lista propriedades para apenas um um sistema de arquivos ZFS ... um conjunto de dados com espaço em branco em seu nome.

O resultado final mais desejável são as propriedades:

  • para todos os sistemas de arquivos ZFS
  • em um arquivo.

Removendo a seguinte string -

&> ${data_directory_path}/ZFS\ file\ system\ properties.txt

- obtém propriedades para todos os sistemas de arquivos ZFS, em uma janela do Terminal, mas não em um arquivo. Isso é o suficiente para eu aceitar uma resposta.

O critério output to file , que não estava em minha primeira edição da questão, pode ser facilmente respondido em outro lugar.

    
por Graham Perrin 06.01.2013 / 18:23

1 resposta

2

Não dividir em espaços

O loop for do bash divide o argumento em todos os caracteres de espaço em branco por padrão. Você poderia de alguma forma escapar de cada linha - ou simplesmente mudar para outro caractere delimitador. cut retornará um valor por linha, portanto, há uma nova linha entre as quais podemos escolher.

Cuidado com as aspas duplas em zfs get all , para que cada $dataset também não seja dividido.

#!/bin/bash
IFS=$'\n'
for dataset in 'zfs list -H | cut -f 1'
do
  zfs get all "$dataset"
done

Redefinindo o IFS

Depois, você pode querer redefinir IFS para o valor anterior, armazená-lo em alguma variável temporária.

OLD_IFS=$IFS
# the whitespaces-sensitive lines
IFS=$OLD_IFS
    
por 14.01.2013 / 11:05