我们最近为我们的组织提供了 JAMF JSS 来管理我们的 Mac,我正在尝试为他们所谓的扩展属性(基本上是自定义库存记录字段)制作一个脚本。我想要的是每台 Mac 都有一个字段来说明 Deep Freeze 的状态。
他们确实有 Deep Freeze 状态的现有模板,但它已经过时并且无法工作。
我确实找到了一个较新的脚本,但可以说它不能开箱即用,因此我对其语法进行了编辑,但后来我注意到即使对于“解冻”的机器,它也会返回“冻结”。
#!/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
我必须编辑它,因为它在第 12 行因语法错误而失败。我将“elif”更改为“else if”,并注释掉了最后一个“fi”,这似乎有效,除了我之前提到的之外。
我发现如果我在“deepfreeze -p status”之后添加-x,它将输出XML。该输出中有以下内容:
<key>bootHow</key>
<integer>x</key>
其中 x 是 0、1 或 2。我发现 0 =冷冻的, 1 =引导解冻以供下次重新启动, 2 =引导解冻。
我想做的是制作一个脚本来查找该键和整数,并返回上述响应之一。
但是我的 awk/sed/等等。技能为 NULL。这是我能想到的最好的办法,当我尝试下一步时却遇到了阻碍:
DFStatus=$(DFXPSWD=Password ./deepfreeze -u User -p status -x | grep -A1 "<key>bootHow</key>"| awk -F'<key>bootHow</key>' '{print $1}')
我以为我可以执行更多 awk 步骤来删除我不想要的文本,但它不起作用。
有什么帮助吗?
答案1
虽然这个解决方案可能看起来更长,但实际上代码少得多,并且易于测试。部分问题似乎是您从质量低劣的脚本开始的。通常具有多个awk
命令的管道可以进行改进。我不知道以下内容是否更适合您的情况,但我希望它能让您更深入地了解解决此问题的一种方法。
要从 xml 流中获取整数值,您可以awk
像这样使用:
awk '
/<key>bootHow<\/key>/ {
getline
gsub("[^0-9]*integer[^0-9]*", "");
print;
}
'
/<key>bootHow<\/key>/
寻址将被大括号内的操作修改的行{ ... }
。getline
将下一行输入读入 $0。下一行应包含整数代码。gsub
删除该行中的所有非数字。print
线。awk
默认情况下不打印行。
将其合并到一个函数中,并编写另一个函数将整数值转换为字符串描述,我们可以得出类似于下面测试的代码的内容。
该boothow
函数封装了awk
前面描述的脚本。
该dfstatus
函数从标准输入读取“bootHow”代码,并在标准输出上打印相应的 df 状态字符串。
该脚本当前已设置用于测试。运行它会在该过程中放入一些测试数据。行调用deepfreeze
被注释掉:
#!/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
在以下记录中,上述脚本保存为./myscript.sh
.
当您运行时. ./myscript.sh
(注意 lone .
),您的交互式 shell 会读取并执行脚本,进入当前的 shell 进程。这些函数将存在并可作为当前 shell 中的命令使用。
$ . ./myscript.sh
boot thawed for next x reboots
现在,命令boothow
anddfstatus
和test_boothow
anddeepfreeze_status
在您当前的 shell 中可用。测试boothow
命令:
$ boothow
<key>bootHow</key>
<integer>2</integer>
2
$ printf '<key>bootHow</key>\n<integer>2</integer>\n' | boothow
2
测试dfstatus
命令,包括退出状态代码 ( $?
):
$ 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
$
答案2
经过一番努力后,我想出了一些行之有效的方法。
#!/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
可能有更好/更优雅的方法,但我想我得到了我想要的。