Como analisar a saída de uma resposta específica (criando Atributo de Extensão para JAMF JSS)

1

Recentemente, recebemos o JAMF JSS para nossa organização para gerenciar nossos Macs, e estou tentando criar um script para o que eles chamam de Atributo de Extensão (basicamente um campo de registro de inventário personalizado). O que eu quero é um campo para cada Mac que diga qual é o status do Deep Freeze.

Eles possuem um modelo existente para o status Deep Freeze, mas estão desatualizados e não funcionam.

Eu encontrei um script mais novo, mas ele não funcionou por assim dizer, então eu o editei para sintaxe, mas depois notei que ele retorna "Frozen" mesmo para máquinas que são "Thawed".

#!/bin/bash

DFStatus=$(DFXPSWD="password" /Library/Application\ Support/Faronics/Deep\ Freeze/deepfreeze -u "user" -p status | grep "Frozen" | awk '{ print $3 }' | awk -F: '{ print $2 }')

if [ ! -f /Library/Application\ Support/Faronics/Deep\ Freeze/deepfreeze ]; then
echo "<result>DeepFreeze not installed.</result>"
elif [ "$DFStatus" == "TRUE" ] ; then
        echo "<result>Frozen</result>"
else
        echo "<result>Thawed</result>"
fi
fi
exit

Eu tive que editá-lo, uma vez que ele falhou com o erro de sintaxe na linha 12. Eu mudei "elif" para "else if" e comentei o último "fi" e pareceu funcionar, exceto como eu disse antes.

Descobri que, se eu adicionar -x logo após "deepfreeze -p status", ele exibirá XML. Na saída, há o seguinte:

<key>bootHow</key>
<integer>x</key>

Onde x é 0, 1 ou 2. Descobri que 0 = congelado , 1 = inicialização descongelada para as próximas x reinicializações , 2 = inicialização descongelado .

O que eu quero fazer é criar um script que procure por aquela chave e número inteiro, e retorne uma das respostas acima.

Mas meu awk / sed / etc. habilidades são NULL. Isso é o melhor que consegui fazer e fiquei frustrada quando tentei dar o próximo passo:

DFStatus=$(DFXPSWD=Password ./deepfreeze -u User -p status -x | grep -A1 "<key>bootHow</key>"| awk -F'<key>bootHow</key>' '{print $1}')

Eu achei que poderia fazer mais etapas do awk removendo o texto que não quero, mas não funcionou.

Alguma ajuda?

    
por Justin_T 04.12.2015 / 18:36

2 respostas

0

Embora esta solução possa parecer mais longa, na verdade é muito menos código e facilmente testável. Parte do problema parece que você começou com um script de baixa qualidade. Normalmente, os pipelines com vários comandos awk podem usar melhorias. Não sei se o seguinte é melhor para a sua situação, mas espero que dê mais informações sobre uma maneira de abordar esse problema.

Para obter o valor inteiro do fluxo xml, você pode usar awk da seguinte forma:

awk '
    /<key>bootHow<\/key>/ {
        getline
        gsub("[^0-9]*integer[^0-9]*", "");
        print;
     }
'
  • /<key>bootHow<\/key>/ endereça a linha que será modificada pelas ações dentro das chaves { ... } .
  • getline lê a próxima linha de entrada em $ 0. Esta próxima linha deve conter o código inteiro.
  • gsub exclui todos os não dígitos da linha.
  • print da linha. awk não imprime linhas por padrão.

Incorporando isso em uma função, e escrevendo outra função para traduzir o valor inteiro na descrição da string, podemos criar algo como o código testado abaixo.

A função boothow encapsula o script awk descrito anteriormente.

A função dfstatus lê os códigos "bootHow" da entrada padrão e imprime as seqüências de status df correspondentes na saída padrão.

O script está atualmente configurado para testes. A execução colocará alguns dados de teste no processo. A linha chamando deepfreeze é comentada:

#!/bin/sh

deepfreeze_status() {
    deepfreeze=/Library/Application\ Support/Faronics/Deep\ Freeze/deepfreeze
    if [ ! -x "$deepfreeze" ]
    then
        status="DeepFreeze not installed"
    else
        status=$(
            DFXPSWD=password "$deepfreeze" -u user -p status -x |
             boothow |
             dfstatus
        )
    fi
    echo "<result>$status</result>"
}

test_boothow() {
    # test boothow and dfstatus functions:
    dfdata='
        <integer>a</integer>
        <key>other1</key>
        <integer>b</integer>
        <key>bootHow</key>
        <integer>1</integer>
        <key>other2</key>
        <integer>c</integer>
    '
    echo "$dfdata" | boothow | dfstatus
}

boothow() {
    awk '
        /<key>bootHow<\/key>/ {
            getline
            gsub("[^0-9]*", "");
            print;
        }
    '
}

dfstatus() {
    while read bhow
    do
        case $bhow in
            0) echo "frozen" ;;
            1) echo "boot thawed for next x reboots" ;;
            2) echo "boot thawed" ;;
            *) echo "unknown status '$bhow'"; return 1 ;;
        esac
    done
}

test_boothow
#deepfreeze_status

Na transcrição a seguir, o script acima foi salvo como ./myscript.sh .

Quando você executa . ./myscript.sh (observe o lone . ), o seu shell interativo lê e executa o script, no seu processo shell atual . As funções existirão e estarão disponíveis como comandos no seu shell atual.

$ . ./myscript.sh
boot thawed for next x reboots

Agora, os comandos boothow e dfstatus e test_boothow e deepfreeze_status estão disponíveis no seu shell atual. Teste o comando boothow :

$ boothow
<key>bootHow</key>
<integer>2</integer>
2
$ printf '<key>bootHow</key>\n<integer>2</integer>\n' | boothow
2

Teste o comando dfstatus , incluindo o código de status de saída ( $? ):

$ dfstatus
0
frozen
1
boot thawed for next x reboots
2
boot thawed
3
unknown status '3'
$ echo $?
1
$
$ echo 1 | dfstatus
boot thawed for next x reboots
$ echo $?
0
$ echo 1 1 | dfstatus
unknown status '1 1'
$ echo $?
1
$
    
por 04.12.2015 / 21:04
0

Depois de fazer um pouco mais do nariz para o rebolo, eu inventei algo que funciona.

#!/bin/bash

# Queries Deep Freeze status and returns either Frozen, Thawed, or Deep Freeze Not Installed
# Replace password and user below with your Deep Freeze user and password

DFStatus=$(DFXPSWD=password /Library/Application\ Support/Faronics/Deep\ Freeze/deepfreeze -u user -p status -x | grep -A1 "<key>bootHow</key>"| awk '{gsub("<key>bootHow</key>", "");print}'| awk '{gsub("<integer>", "");print}' | awk '{gsub("</integer>", "");print}')

if [ ! -f /Library/Application\ Support/Faronics/Deep\ Freeze/deepfreeze ]; then
echo "<result>DeepFreeze not installed.</result>"
fi

if [ "$DFStatus" -eq "0" ]; then
        echo "<result>Frozen</result>"
fi

if [ "$DFStatus" -eq "1" ] || [ "$DFStatus" -eq "2" ] ; then
        echo "<result>Thawed</result>"
fi

exit

Pode haver maneiras melhores / mais elegantes, mas acho que consegui o que queria.

    
por 04.12.2015 / 20:07