1

We recently got JAMF JSS for our organization to manage our Macs, and I'm trying to make a script for what they call an Extension Attribute (basically a custom inventory record field). What I want is a field for each Mac that tells what the status of Deep Freeze is.

They do have an existing template for Deep Freeze status, however it is out of date and won't work.

I did find a newer script, but it didn't work out of the box so to speak, so I edited it for syntax, but then I noticed that it returns "Frozen" even for machines that are "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

I had to edit it since it failed with syntax error on line 12. I changed "elif" to "else if" and commented out the last "fi" and that seemed to work, except as I noted before.

I found that if I add -x just after "deepfreeze -p status", it will output XML. In that output there is the following:

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

Where x is 0, 1, or 2. I figure out that 0 = frozen, 1 = boot thawed for next x reboots, 2 = boot thawed.

What I want to do is make a script that looks for that key and integer, and returns one of the above responses.

But my awk/sed/etc. skills are NULL. This is the best I was able to come up with and I got stymied when I tried to go the next step:

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

I thought I could just do more steps of awk removing the text I don't want, but it didn't work.

Any help?

1
  • We can't really help without having the input you are trying to parse. Please edit your question and show us the output of DFXPSWD="password" /Library/Application\ Support/Faronics/Deep\ Freeze/deepfreeze -u "user" -p status for a frozen and a thawed machine. Either that or the XML output but we need something to parse. Commented Dec 4, 2015 at 18:52

2 Answers 2

0

While this solution may look longer, it is actually much less code, and easily testable. Part of the problem appears that you started with a poor quality script. Usually pipelines with multiple awk commands can use improvement. I don't know if the following is better for your situation, but I hope it gives more insight into one way to approach this problem.

To get the integer value from the xml stream, you can use awk like this:

awk '
    /<key>bootHow<\/key>/ {
        getline
        gsub("[^0-9]*integer[^0-9]*", "");
        print;
     }
'
  • /<key>bootHow<\/key>/ addresses the line which will be modified by the actions within the braces { ... }.
  • getline reads the next line of input into $0. This next line should contain the integer code.
  • gsub deletes all non-digits from the line.
  • print the line. awk does not print lines by default.

Incorporating that into a function, and writing another function to translate the integer value into the string description, we can come up with something like the tested code below.

The boothow function encapsulates the awk script previously described.

The dfstatus function reads "bootHow" codes from standard input and prints corresponding df status strings on standard output.

The script is currently set up for testing. Running it will put some test data through the process. The line calling deepfreeze is commented out:

#!/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

In the following transcript the above script was saved as ./myscript.sh.

When you run . ./myscript.sh (notice the lone .), your interactive shell reads and executes the script, into your current shell process. The functions will exist and are available as commands in your current shell.

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

Now, the commands boothow and dfstatus and test_boothow and deepfreeze_status are available in your current shell. Test the boothow command:

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

Test the dfstatus command, including exit status code ($?):

$ 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
$
0

After doing some more nose to the grindstone, I came up with something that works.

#!/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

There may be better/more elegant ways, but I think I got what I wanted.

1
  • Instead of piping the grep to all of those awks, try piping the grep -A1 output to awk '/integer/ { gsub("[^0-9]*integer[^0-9]*", ""); print }' ? Commented Dec 4, 2015 at 20:13

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.