Gestion des espaces dans le nom d'un jeu de données ZFS dans un script shell

1

Je voudrais prendre la sortie de deux commandes -

zpool list
zfs list

et pour chaque piscine trouvée:

zpool get all nameofpool

et pour chaque système de fichiers trouvé:

zfs get all nameoffilesystem

Contexte et environnement

Je fais des changements locaux au script qui fait partie intégrante d'OS X,

/usr/bin/sysdiagnose

  • #!/bin/sh pour commencer
  • toujours exécuté avec les privilèges de superutilisateur
  • parfois efficacement sans tête ( déclenché par un accord de clé ), le résultat doit donc être un fichier.

Première expérience

D'après l'exemple de # 65, supprimez tous les instantanés ZFS :

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

Cela fonctionne, mais pas là où il y a un espace dans le nom du jeu de données. Par exemple, où le système de fichiers est zhandy/Pocket Time Machinela sortie comprend:

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

 Deuxième expérience

… Était basé sur la première réponse à cette question - utiliser IFS- et rendait le script plus semblable à celui d'Apple. Voir révision 4 .

Troisième expérience

Basé sur la réponse acceptée à cette question - avec IFS, et guillemets pour "$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

Parmi les fichiers résultants, ZFS file system properties.txtrépertorie les propriétés d'un seul système de fichiers ZFS: un jeu de données avec un espace dans son nom.

Le résultat final le plus souhaitable est les propriétés:

  • pour tous les systèmes de fichiers ZFS
  • dans un fichier.

Supprimer la chaîne suivante -

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

- obtient les propriétés de tous les systèmes de fichiers ZFS, dans une fenêtre de Terminal mais pas dans un fichier. Cela me suffit pour accepter une réponse.


Le critère de sortie dans un fichier , qui ne figurait pas dans ma première édition de la question, peut être facilement répondu ailleurs.

Graham Perrin
la source
Chat, en référence à la deuxième édition de cette question: chat.stackexchange.com/transcript/message/7661588#7661588
Graham Perrin le
À côté de la réponse acceptée ci-dessous, avec cette réponse ( Comment puis-je prendre la sortie d’un script shell et la placer dans un fichier sur la ligne de commande? ) Je me rends compte que pour la sortie vers un fichier - pour l’ ajout - j’ai besoin >>(non &>ou &>>). Dans les commentaires adressés à Apple, j'ai demandé sysdiagnoseà être ajouté à Apple Open Source . Si cela se produit, je rendrai publiques mes autres modifications apportées au script, dont la plupart ne sont pas liées à ZFS.
Graham Perrin
Appréciant l'âge de la question et la simplifiant pour simplifier, qu'est-ce qui n'allait pas avec simplement for DS in $(zfs list -H -o name); do zfs get all "$DS"; done? Cela fait un moment que j'utilise cet idiome dans mes propres scripts et j'espère n'avoir rien oublié (notez l'utilisation de -o nameand- "quoting pour limiter la sortie (dont vous n'avez plus besoin cut) et gérer les espaces dans les noms de jeu de données (même si espace est supposé être un caractère invalide pour les noms de jeu de données)
jimbobmcgee

Réponses:

2

Ne pas diviser en espaces

La forboucle de bash divise l'argument par défaut pour tous les caractères d'espacement. Vous pouvez en quelque sorte échapper à chaque ligne - ou simplement basculer vers un autre caractère de délimitation. cutretournera une valeur par ligne, donc il y a une nouvelle ligne entre nous que nous pouvons choisir.

Faites attention aux doubles guillemets zfs get all, afin que chacun $datasetne soit pas divisé non plus.

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

Réinitialisation IFS

Ensuite, vous voudrez peut-être rétablir IFSla valeur avant, la stocker dans une variable temporaire.

OLD_IFS=$IFS
# the whitespaces-sensitive lines
IFS=$OLD_IFS
Jens Erat
la source
1
Cette opération (coller) crée des propriétés pour un seul jeu de données . Une approche alternative échoue d'une manière différente . pastebin.com/nJQZq64s affiche les jeux de données au moment de la rédaction. Devrais-je modifier la question d'origine pour inclure plus de détails?
Graham Perrin
Oui, utiliser /bin/shfonctionne pour moi sur OS X (liens bashici), mais je rencontre les mêmes problèmes sur Ubuntu Linux (lien shvers dash). Essayez de changer le shebang (voir la réponse mise à jour), dashne semble pas interpréter le caractère \ncomme nouvelle ligne, mais le caractère 'n'. PS: +1 pour votre propre effort dans la résolution du problème et l'ajout d'un lien vers la zfs listsortie de la question ne ferait de mal à personne, mais offrirait une référence. Soit dit en passant, vos onglets ont été remplacés par des espaces lors du téléchargement, il a fallu annuler cela avant de cutfonctionner correctement.
Jens Erat
/bin/bashn'a pas contourné. J'ai édité la question pour inclure plus de contexte et pour montrer plus clairement comment j'expérimente à partir de cette réponse. Succès partiel. Je pourrais faire une erreur très basique quelque part! Merci…
Graham Perrin
1
Oh, vous avez un autre problème, ce n'est pas celui que j'avais - ne pas réaliser cela en creusant à vos pâtes pour la première fois ... L' utilisation printfa été inutilement compliqué quand même, l' envelopper dans des guillemets doubles: zfs get all "$dataset". Je suppose que ça devrait bien se passer maintenant.
Jens Erat