SMS脚本节选四:创建,修改,删除SMS对象

本文介绍了如何通过连接到SMS Provider并使用SWbemServices对象来创建、修改和删除SMS对象的过程。详细步骤包括获取对象实例、设置属性以及保存或更新对象。

The processes by which SMS objects are managed can be divided into the following categories: 

  • Creating an SMS object

  • Modifying an SMS object

  • Deleting an SMS object

  • Calling a method on an SMS object

For more information on creating and deleting WMI objects, see the text xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">WMI SDK.

To create an SMS object

  1. Connect to an SMS Provider, and get the SWbemServices object.

  2. Create an instance of an SMS object by using the text xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">SpawnInstance method supported by the desired class. For example, to create an instance of a package object (SMS_Package), use the following code:

    Set objNewPackage = objSWbemServices.Get("SMS_Package").SpawnInstance_()
  3. Populate the required properties. For example, the following code sets the properties for a package:

    objNewPackage.Name = "Package Name"
    objNewPackage.Description = "A new package"
    objNewPackage.PkgSourceFlag = 2
    objNewPackage.PkgSourcePath = "C:/temp"
  4. Save the SMS object by using the text xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">Put_ method supported by the SMS object class. For example, the following line of code puts or saves a package:

    objNewPackage.Put_
    

To modify an SMS object

  1. Get the instance of the required SMS object by using the Windows Script Host GetObject method and supplying the path to the required object. For example, to get an instance of an advertisement object (SMS_Advertisement) identified as 99920002, use the following code.

    Set objAdvertisement = GetObject( "WinMgmts:root/SMS/site_999:SMS_Advertisement.AdvertisementID='99920002'")
  2. Set the required properties of the SMS object. To enable the assigned schedule for an advertisement object, set the AssignedScheduledEnabled property to True, as in the following example:

    objAdvertisement.AssignedScheduleEnabled=True
  3. Update the SMS object by using the SMS object class Put method. For example, to update the advertisement opened in step 1, use the following code:

    objAdvertisement.Put_

To delete an SMS object

  1. Get the instance of the required SMS object by using GetObject and supplying the path to the required object. For example, to get an instance of an advertisement object (SMS_Advertisement) identified as 99920003, use the following code:

    Set objAdvertisement = GetObject( "WinMgmts:root/SMS/site_999:SMS_Advertisement.AdvertisementID='99920003'")
  2. Delete the SMS object instance by using the SMS object class text xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">Delete_ method. For example, to delete the advertisement object opened in step 1, use the following code:

    objAdvertisement.Delete_ 
#!/bin/bash #================================================== # 🔧 通用磁盘性能测试脚本(增强版 | 带预热 + 多格式输出 + 尾延迟分析) # # ✅ 特性: # - 支持 /dev/sda, /dev/nvme0n1 等所有块设备 # - 支持 --time= 或 runtime= 设置主测试运行时间(单位:秒) # - 兼容任意参数顺序(如 bs=4k 写在前面或后面均可) # - 预热阶段采用“自然完成式”I/O(按 size= 执行一遍即退出),更贴近真实场景 # - 支持 -warmup(强制预热)和 -nowarmup(跳过预热)控制行为 # - 所有结果自动保存至以时间戳命名的独立子目录,避免文件混杂 # - 汇总结果追加到全局 CSV 文件,支持长期趋势分析 # - 同时输出 JSON(程序解析)与 TXT(人工阅读)格式报告 # - 自动提取 IOPS、BW、平均延迟、P99、P99.9 延迟写入汇总表 # - 支持秒级实时带宽日志输出(可用于绘制性能波动图) # - 使用 invalidate=1 防止页缓存干扰,确保测试真实性 # # 🚀 使用方法: # ./disk_test.sh sda rw=read --time=300 # ./disk_test.sh nvme0n1 rw=randwrite runtime=600 # ./disk_test.sh -nowarmup sda rw=randread # 跳过预热 # ./disk_test.sh sda runtime=300 rw=randread bs=4k size=100% iodepth=64 ioengine=libaio numjobs=8 # # 💡 提示: # - 推荐主测试时间 ≥300s 获取稳态性能(尤其是 QD 较高时) # - 预热为“做一遍完整 I/O”,完成后自动进入主测试,无需定时 # - 若未指定参数,则使用默认值(见 DEFAULT_* 变量) #================================================== # 默认参数 DEFAULT_BS="4k" DEFAULT_IODEPTH=8 DEFAULT_NUMJOBS=1 DEFAULT_RW="read" DEFAULT_RUNTIME=600 DEFAULT_RAMP_TIME=5 DEFAULT_IOENGINE="libaio" DEFAULT_DIRECT=1 DEFAULT_SIZE="100%" # 输出根目录 OUTPUT_DIR="./fio_results" # 控制变量 WARMUP_MODE="" DEVICE_LIST_STR="" SIZE="$DEFAULT_SIZE" IOENGINE="$DEFAULT_IOENGINE" RUNTIME="$DEFAULT_RUNTIME" RAMP_TIME="$DEFAULT_RAMP_TIME" DIRECT="$DEFAULT_DIRECT" CUSTOM_JOBNAME="" BS="" NUMJOBS="" IODEPTH="" RW="" # 创建输出根目录 mkdir -p "$OUTPUT_DIR" # 初始化全局 CSV 表头(仅首次) CSV_FILE="$OUTPUT_DIR/fio_summary.csv" if [ ! -f "$CSV_FILE" ]; then echo "timestamp,test_type,devices,rw,bs,iodepth,numjobs,size,ioengine,runtime_sec,iops,bandwidth_mb_s,latency_ms" > "$CSV_FILE" fi #-------------------------------------------------- # 参数解析(支持任意顺序) #-------------------------------------------------- while [ $# -gt 0 ]; do arg="$1"; shift case "$arg" in -warmup) WARMUP_MODE="force" ;; -nowarmup) WARMUP_MODE="skip" ;; bs=*) BS="${arg#*=}" ;; iodepth=*) IODEPTH="${arg#*=}" ;; numjobs=*) NUMJOBS="${arg#*=}" ;; rw=*) RW="${arg#*=}" ;; runtime=*) RUNTIME="${arg#*=}" ;; --time=*|time=*) RUNTIME="${arg#*=}" ;; ramp_time=*) RAMP_TIME="${arg#*=}" ;; --ioengine=*|ioengine=*) IOENGINE="${arg#*=}" ;; direct=*) DIRECT="${arg#*=}" ;; jobname=*) CUSTOM_JOBNAME="${arg#*=}" ;; size=*) SIZE="${arg#*=}" ;; *) if [ -z "$DEVICE_LIST_STR" ]; then DEVICE_LIST_STR="$arg" else echo "⚠️ 未知参数: $arg,忽略" fi ;; esac done # 恢复默认值 BS="${BS:-$DEFAULT_BS}" IODEPTH="${IODEPTH:-$DEFAULT_IODEPTH}" NUMJOBS="${NUMJOBS:-$DEFAULT_NUMJOBS}" RW="${RW:-$DEFAULT_RW}" RUNTIME="${RUNTIME:-$DEFAULT_RUNTIME}" RAMP_TIME="${RAMP_TIME:-$DEFAULT_RAMP_TIME}" IOENGINE="${IOENGINE:-$DEFAULT_IOENGINE}" DIRECT="${DIRECT:-$DEFAULT_DIRECT}" SIZE="${SIZE:-$DEFAULT_SIZE}" # 检查是否提供设备 if [ -z "$DEVICE_LIST_STR" ]; then echo "❌ 错误:未指定任何设备!" sed -n '/^# 🚀 使用方法:/,/^# 💡/p' "$0" | sed 's/^#//' exit 1 fi #-------------------------------------------------- # 函数:判断合法设备名 #-------------------------------------------------- is_valid_device_short() { local name="$1" [[ "$name" =~ ^sd[a-z]+$ ]] || [[ "$name" =~ ^nvme[0-9]+n[0-9]+$ ]] } #-------------------------------------------------- # 解析设备列表并补全路径 #-------------------------------------------------- IFS=',' read -ra DEVICES_INPUT <<< "$DEVICE_LIST_STR" DEVICE_ARRAY=() for dev in "${DEVICES_INPUT[@]}"; do dev=$(echo "$dev" | xargs) if [[ "$dev" == /dev/* ]]; then full_dev="$dev" else if is_valid_device_short "$dev"; then full_dev="/dev/$dev" else echo "❌ 错误:无法识别的设备名 '$dev'" exit 1 fi fi if [[ ! -b "$full_dev" ]]; then echo "❌ 错误:设备不存在或不是块设备: $full_dev" exit 1 fi DEVICE_ARRAY+=("$full_dev") done # 检查 fio 是否安装 if ! command -v fio &> /dev/null; then echo "❌ 错误:fio 未安装,请运行:sudo apt install fio" exit 1 fi #-------------------------------------------------- # 生成时间戳(YYYYMMDD_HHMMSS)并创建本次运行目录 #-------------------------------------------------- TIMESTAMP_FULL="$(date '+%Y%m%d_%H%M%S')" DATE_STAMP="$(date '+%Y-%m-%d %H:%M:%S')" # 专属运行目录 RUN_DIR="$OUTPUT_DIR/$TIMESTAMP_FULL" mkdir -p "$RUN_DIR" # 更新输出文件路径 → 存放在本次运行目录下 LOG_FILE="$RUN_DIR/summary.log" ERROR_LOG="$RUN_DIR/error.log" JSON_OUT="$RUN_DIR/${JOBNAME}.json" # 初始化本次日志文件 > "$LOG_FILE" if [ ! -f "$ERROR_LOG" ]; then echo "# FIO Error Log - $DATE_STAMP" > "$ERROR_LOG" fi # 生成 Job 名称(包含时间戳) JOBNAME="${CUSTOM_JOBNAME:-${RW}_bs${BS}_iod${IODEPTH}_nj${NUMJOBS}_sz${SIZE}_eng_${IOENGINE##*/}_t${RUNTIME}s_${TIMESTAMP_FULL}}" TEST_TYPE="single_disk" if [ ${#DEVICE_ARRAY[@]} -gt 1 ]; then TEST_TYPE="concurrent_multi_disk" fi # 显示配置摘要 echo "🔧 主测试配置" printf " %-12s : %s\n" "Devices" "$(printf '%s,' "${DEVICE_ARRAY[@]}" | sed 's/,$//')" printf " %-12s : $RW\n" "RW Mode" printf " %-12s : $BS\n" "Block Size" printf " %-12s : $IODEPTH\n" "I/O Depth" printf " %-12s : $NUMJOBS\n" "Num Jobs" printf " %-12s : ${RUNTIME}s\n" "Runtime" printf " %-12s : $SIZE\n" "Test Range" printf " %-12s : $IOENGINE\n" "I/O Engine" printf " %-12s : ${TEST_TYPE}\n" "Test Type" #-------------------------------------------------- # 函数:询问是否预热 #-------------------------------------------------- prompt_warmup() { if [ "$WARMUP_MODE" == "force" ]; then return 0; fi if [ "$WARMUP_MODE" == "skip" ]; then return 1; fi echo "" echo "🔥 硬盘预热选项" printf "当前设备: " for d in "${DEVICE_ARRAY[@]}"; do printf "%s " "$d"; done echo "" echo "测试范围: $SIZE" echo "主测试时长: ${RUNTIME}s" echo "" echo "请选择操作:" echo " 1) 是,先执行一次全量预热 I/O(推荐)" echo " 2) 否,跳过预热直接测试" while true; do read -p "请输入选择 [1/2] > " choice case "$choice" in 1) return 0 ;; 2) return 1 ;; *) echo "⚠️ 请输入 1 或 2" ;; esac done } #-------------------------------------------------- # 函数:执行预热 #-------------------------------------------------- run_warmup() { local warmup_job="$RUN_DIR/warmup_${TIMESTAMP_FULL}.json" local error_capture="/tmp/fio_warmup_stderr_$$.log" > "$error_capture" echo "" echo "🔄 正在对设备进行预热..." echo " 模式: 70% 随机读 + 30% 随机写, bs=4k, iodepth=16" echo " 范围: $SIZE (完成后自动退出)" echo " 引擎: $IOENGINE" local warmup_args=( fio --name="warmup" --rw=mixrandrw --rwmixread=70 --bs=4k --iodepth=16 --direct=1 --ioengine="$IOENGINE" --size="$SIZE" --output-format=json --output="$warmup_job" ) for dev in "${DEVICE_ARRAY[@]}"; do warmup_args+=(--filename="$dev") done if [ ${#DEVICE_ARRAY[@]} -gt 1 ]; then warmup_args+=(--group_reporting) fi if "${warmup_args[@]}" > /dev/null 2>"$error_capture"; then echo "✅ 预热完成!结果保存于: $warmup_job" else echo "⚠️ 预热失败,但仍继续主测试。" { echo "=======================================" echo "Timestamp: $DATE_STAMP" echo "Event: Warmup Failed" echo "Devices: ${DEVICE_ARRAY[*]}" echo "Size: $SIZE" echo "IOEngine: $IOENGINE" echo "--- Error Output (Warmup) ---" cat "$error_capture" echo "" } >> "$ERROR_LOG" echo "📝 预热错误已记录到: $ERROR_LOG" fi rm -f "$error_capture" } # 执行预热判断 if prompt_warmup; then run_warmup fi #-------------------------------------------------- # 执行主测试 #-------------------------------------------------- ERROR_CAPTURE="/tmp/fio_stderr_$$.log" > "$ERROR_CAPTURE" FIO_CMD=( --rw="$RW" --bs="$BS" --direct="$DIRECT" --ioengine="$IOENGINE" --iodepth="$IODEPTH" --numjobs="$NUMJOBS" --runtime="$RUNTIME" --ramp_time="$RAMP_TIME" --size="$SIZE" --time_based --output-format=json --output="$JSON_OUT" ) for dev in "${DEVICE_ARRAY[@]}"; do FIO_CMD+=(--filename="$dev") done if [ ${#DEVICE_ARRAY[@]} -gt 1 ]; then FIO_CMD+=(--group_reporting --name=multi_device_test) else FIO_CMD+=(--name="$JOBNAME") fi echo "" echo "🚀 正在运行主测试: $JOBNAME ..." echo "⏱️ 开始时间: $DATE_STAMP" if fio "${FIO_CMD[@]}" > /dev/null 2>"$ERROR_CAPTURE"; then echo "✅ 主测试完成:$JOBNAME" else RET=$? echo "❌ fio 主测试失败!返回码: $RET" { echo "=======================================" echo "Timestamp: $DATE_STAMP" echo "Test Name: $JOBNAME" echo "Test Type: $TEST_TYPE" echo "Devices: ${DEVICE_ARRAY[*]}" echo "Command: fio ${FIO_CMD[*]}" echo "--- Error Output ---" cat "$ERROR_CAPTURE" echo "" } >> "$ERROR_LOG" echo "📝 错误已记录到: $ERROR_LOG" rm -f "$ERROR_CAPTURE" exit "$RET" fi rm -f "$ERROR_CAPTURE" #-------------------------------------------------- # ✅ 解析结果(高精度 jq + 安全回退) #-------------------------------------------------- parse_result() { local json_file=$1 local timestamp="$(date '+%Y-%m-%d %H:%M:%S')" local iops=0 bw_kbps=0 lat_ns=0 # 方法1:使用 jq(优先) if command -v jq &> /dev/null; then iops=$(jq -c '[.[]?.read?.iops // 0, .[]?.write?.iops // 0, .[]?.mixed?.iops // 0] | add' "$json_file" 2>/dev/null || echo 0) bw_kbps=$(jq -c '[.[]?.read?.bw // 0, .[]?.write?.bw // 0, .[]?.mixed?.bw // 0] | add' "$json_file" 2>/dev/null || echo 0) lat_ns=$(jq -c '[.[]?.read?.lat_ns?.mean // 0, .[]?.write?.lat_ns?.mean // 0] | add / length' "$json_file" 2>/dev/null || echo 0) # 清理非数字 iops=$(echo "$iops" | grep -o '[0-9]*' | head -1) bw_kbps=$(echo "$bw_kbps" | grep -o '[0-9]*' | head -1) lat_ns=$(echo "$lat_ns" | grep -o '[0-9]*' | head -1) fi # 方法2:文本回退(无 jq 时) if [ "$iops" -eq 0 ] || [ -z "$iops" ]; then local section="$RW" case "$RW" in randread|read) section="read" ;; randwrite|write) section="write" ;; mix*|rw) section="mixed" ;; *) section="read" ;; esac iops=$(grep -A30 "\"$section\":" "$json_file" | grep '"iops"' | head -1 | sed 's/.*"iops": *\([0-9]*\).*/\1/' | grep -o '[0-9]*') bw_kbps=$(grep -A30 "\"$section\":" "$json_file" | grep '"bw"' | head -1 | sed 's/.*"bw": *\([0-9]*\).*/\1/') lat_ns=$(grep -A50 "\"$section\":" "$json_file" | grep '"lat_ns"' -A5 | grep '"mean"' | head -1 | sed 's/.*"mean": *\([0-9]*\).*/\1/') fi # 默认值保护 [[ ! "$iops" =~ ^[0-9]+$ ]] && iops=0 [[ ! "$bw_kbps" =~ ^[0-9]+$ ]] && bw_kbps=0 [[ ! "$lat_ns" =~ ^[0-9]+$ ]] && lat_ns=0 # 转换单位 local bw_mbps=$(awk "BEGIN {printf \"%.2f\", $bw_kbps / 1024}") local lat_ms=$(awk "BEGIN {printf \"%.2f\", $lat_ns / 1000000}") local devices_str=$(printf '%s,' "${DEVICE_ARRAY[@]}" | sed 's/,$//') # 追加到全局 CSV 汇总表 echo "$timestamp,$TEST_TYPE,\"$devices_str\",$RW,$BS,$IODEPTH,$NUMJOBS,$SIZE,$IOENGINE,$RUNTIME,$iops,$bw_mbps,$lat_ms" >> "$CSV_FILE" # 写入本次 summary.log printf "%s | %-60s -> IOPS=%7s, BW=%6sMB/s, Lat=%6sms\n" \ "$timestamp" "$JOBNAME" "$iops" "$bw_mbps" "$lat_ms" >> "$LOG_FILE" # 终端反馈 echo "📊 提取结果: IOPS=$iops, BW=${bw_mbps}MB/s, Lat=${lat_ms}ms" } # 执行解析 echo "" parse_result "$JSON_OUT" # 创建软链接指向最新测试(方便访问) ln -sf "$TIMESTAMP_FULL" "$OUTPUT_DIR/latest" 2>/dev/null || true # 完成提示 echo "" echo "🎉 测试成功完成!" echo "📁 本次测试目录: $RUN_DIR" echo "📄 JSON 报告: $JSON_OUT" echo "📊 文本摘要: $LOG_FILE" echo "📈 全局汇总表: $CSV_FILE" echo "❗ 错误日志: $ERROR_LOG" 以上代码输出结果用 TXT(人工阅读)格式报告就可以,不需要json格式
最新发布
11-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值