操作promethean panel普米的相关shell脚本
可以使用shell脚本做菜单列表
根据自己的需求去选择当前想要做的事情
echo ' ###############便捷骚操作############### ' i=1 while((i <= 10000)) do function menuList { echo ' 菜单列表: 一: Panel adb: 1-1: 查看当前已连接的panel设备 1-2: 断开所有panel设备 1-3: 连接panel设备 1-4: 删除panel agent 1-5: 安装软件 1-6:清理环境 1-7: panel logcat输出到本地 1-8: 本地文件传输到panel 1-9: 查看设备 MAC地址 1-10:查看设备 SN 1-11:切换环境 1-12:重启 1-13:关机 1-14:查看panel任务 1-15:查看设备序列号 1-16:AP7B 150 修改序列号 1-17:设备录屏 1-18:设备设置和移除代理 二: Portal api: 2-1: 获取登录token 2-2:临时邮箱注册promethean账号 2-3: 注册第三方微软组织账号 2-4: 新panel checkin 2-5: panel enroll 2-6: panel transfer 2-7: panel manage site 2-8: 获取组织列表和sites 列表 2-9: 显示指定org/site下的panels列表 2-10: 添加新的Radix QaFirmware panel版本 2-11: 账号重置eula状态 三: IDP api: 3-1: 获取登录的设备列表 3-2:登录新设备 3-3:登出设备 3-4: 更新panel settings壁纸 3-5: NFC ' read -p "请选择你的选项(例如1-1): " menu } function typeList { echo ' 操作类型列表: 1: 单个 2: 批量 ' read -p "请选择操作类型:" type } function env_init { #环境初始化 echo ' 环境列表: 1: dev 2: sandbox 3: ohstaging 4: prod ' read -p "请选择环境(例如1): " env case $env in 1) envUrl="https://devapi.prometheanproduct.com" email="chenrj@nd.com.cn" password="Jin_111111" apiKey_token="b0p31d5rm8ifd93132cfolmsa01yc60u4nd79btg" apiKey_pm="bv6d45mobai6lk31l9sw6s9argxn42x0x35j7jlt" apiKey_um="hibkxo48a90bxkeaw22du9w01xnoy64y2itsmgv9" apiKey_os="8k7m8b5d5fe4uainvosm1ph3aaw1kgvgh4toixcx" apiKey_integration="y14v59tlgyczjp3encuc07ca6pnj4msj94mj53pp" bundleId="ASSET:BUNDLE:b8534cc0-0bd5-435e-bbef-3a0b66def4f3" stuff="-env-dev" org_public="6eb5850f-2aa5-508e-9c9d-e0d6dd2ae4f2";; 2) envUrl="https://sandboxapi.prometheanproduct.com" email="chenrj@nd.com.cn" password="Jin_111111" apiKey_token="l4mfs8uak1wglsxsyr4ada8h0d0179fwwlrgrzxg" apiKey_pm="ffk2es1wc2q36r91uq79o4ow65qfkaqn8xhl5ml3" apiKey_um="9df3s1p1asihvujg0rigw3v5rdmpg3olrcwlv2wg" apiKey_os="uvw9493jpylxyzoww77c6pdhzo445mu82b9h03ja" apiKey_integration="2rc9mqljkbcmt17ugbws62awp4or7beckzw1tnw6" bundleId="ASSET:BUNDLE:384e52e0-15d7-4270-b691-281d53883ae9" stuff="" org_public="e0b594a6-79df-6fea-03a9-31abeeca9f8a";; 3) envUrl="https://api.staging.mypromethean.com" email="chenrj@nd.com.cn" password="Jin_111111" apiKey_token="3ca4wndiwle7aenp6bsqr5w6c6fo8ark8mspgloc" apiKey_pm="0i3gc7uttwvhfvgbfiqhtftbm0v2t2f05b20ulfy" apiKey_um="ihi8jenc22h37w2gyjvt395iyx75tkbi13qt3ypj" apiKey_os="lvs656pldskhp2b9ryxz00ng4yo8f3rajv4f8kd8" apiKey_integration="am7r4574j0hu445rvcgypegeng9a5ppfqkoi9evb" bundleId="ASSET:BUNDLE:ce6658cd-7198-4dcf-a133-e74c6578e054" stuff="" org_public="aebb3b60-72f9-b9bb-03bf-9a3902743915";; 4) envUrl="https://api.mypromethean.com" email="chenrj@nd.com.cn" password="Jin_owen930926" apiKey_token="0rx9owt77ggnq47odona8bvu35k71a7sjpp4m5p9" apiKey_pm="9e7dl5dtxel8h5c41c40akxxf47qcr0rbjg06m0n" apiKey_um="328ikrz4gmsbp0vzfh8m9zckxuf100p5x4lh5599" apiKey_os="d8e8wkdumnxcrx74htsfowj9bx5xqy5f1995xq62" apiKey_integration="暂时未知待后续补充" bundleId="ASSET:BUNDLE:f1aed4a7-11ce-4494-bd7b-74dcd4efda89" stuff="" org_public="fcb5a6c2-045a-bc47-a776-d21991ad7a7a" esac #get_authorization_token api="/identity/login" echo "获取登录Token:" res=$(curl -i -X POST $envUrl$api \ -H "Content-Type:application/json" \ -H "x-api-key:$apiKey_token" \ -d \ '{ "email":"'$email'" , "password":"'$password'" }' ) token1=${res#*IdToken} token2=${token1:3} token3=${token2%%user_sub*} Authorization=${token3::-4} echo -e "登录token: $Authorization\n" } #============================================================================================================公共部分===================================================================================================================================================== function run { clear case $menu in 1-1) #看当前已连接的panel设备 adb devices;; 1-2) # 断开所有panel设备 adb disconnect 192.168.84.110 adb disconnect 192.168.84.149 adb disconnect 192.168.84.150 adb disconnect 192.168.84.152 echo "已经断开所有panel设备";; 1-3) #连接panel设备 adb disconnect 192.168.84.110 adb disconnect 192.168.84.149 adb disconnect 192.168.84.150 adb disconnect 192.168.84.152 echo -e "已经断开所有panel设备\n" echo '设备列表: A: 192.168.84.149 B: 192.168.84.150 U: 192.168.84.152 IP: 手动输入IP ' read -p "选择你要连接的设备(A/B/U/a/b/u/ip/IP): " panel case $panel in A) adb connect 192.168.84.149:5555;; B) adb connect 192.168.84.150:5555;; U) adb connect 192.168.84.152:5555;; a) adb connect 192.168.84.149:5555;; b) adb connect 192.168.84.150:5555;; u) adb connect 192.168.84.152:5555;; IP) read -p "请输入你要连接的ip(比如192.168.84.149):" ip adb connect $ip:5555;; ip) read -p "请输入你要连接的ip(比如192.168.84.149):" ip adb connect $ip:5555;; esac;; 1-4) #删除panel agent adb shell pm uninstall com.nd.promethean.mdmagent;; 1-5) #安装软件 echo " 方法1:通过scrcpy工具配合直接拖入安装 方法2:通过输入apk所在位置push安装 " read -p "请选择方法(1/2):" way case $way in 1) scrcpy --push-target sdcard/Download/;; 2) read -p "请输入apk绝对本地路径,例如D:/desk/qq.apk: " fileAddress echo "将apk 传输 到设备的sdcard/Download/中" adb push $fileAddress sdcard/Download/ echo "" echo "apk 列表如下:" adb shell busybox find sdcard/Download/ -name "*.apk" read -p "选择要安装的apk名,例如qq: " apkName echo "开始安装apk中" adb shell pm install -r sdcard/Download/$apkName.apk; esac;; 1-6) #清理环境 adb root adb shell rm -r data/data/com.nd.promethean.mdmagent/files/.PanelManagementCompat ;; 1-7) #panel logcat输出到本地 echo "logcat输出到本地D:/desk/log.txt" adb logcat > D:/desk/log.txt;; 1-8) #本地文件传输到panel echo "文件传输到panel的sdcard/Download/ 中" echo " 方法1:通过scrcpy工具配合直接拖入 方法2:通过输入文件所在位置传输 " read -p "请选择方法(1或2):" way case $way in 1) scrcpy --push-target sdcard/Download/;; 2) echo "输入文件绝对名称例如“D:/desk/1/*” 或 “D:/desk/log.txt” " read -p "输入文件名称: " fileAddress adb push $fileAddress sdcard/Download/;; *) echo "请重新输入,输入值未1或2";; esac;; 1-9) #查看panel MAC地址 echo "Ethernet MAC Address:" adb shell cat sys/class/net/eth0/address echo -e "" echo "wifi MAC Address:" adb shell cat sys/class/net/wlan0/address;; 1-10) #查看设备 SN adb shell getprop ro.serialno;; 1-11) #切换环境 echo ' 环境列表: 1: dev 2: sandbox 3: ohstaging 4: prod ' read -p "请选择环境(例如1): " env case $env in 1) adb shell rm -r sdcard/PanelManagementConfig/ adb shell rm -r sdcard/PanelManagement/ adb shell mkdir sdcard/PanelManagementConfig/ adb shell mkdir sdcard/PanelManagement/ adb push E:/ND/Panel/Panel_Switch_Env/env/dev/local_configuration.conf sdcard/PanelManagementConfig/ adb push E:/ND/Panel/Panel_Switch_Env/env/dev/local_configuration.conf sdcard/PanelManagement/;; 2) adb shell rm -r sdcard/PanelManagementConfig/ adb shell rm -r sdcard/PanelManagement/ adb shell mkdir sdcard/PanelManagementConfig/ adb shell mkdir sdcard/PanelManagement/ adb push E:/ND/Panel/Panel_Switch_Env/env/sandbox/local_configuration.conf sdcard/PanelManagementConfig adb push E:/ND/Panel/Panel_Switch_Env/env/sandbox/local_configuration.conf sdcard/PanelManagement/;; 3) adb shell rm -r sdcard/PanelManagementConfig/ adb shell rm -r sdcard/PanelManagement/ adb shell mkdir sdcard/PanelManagementConfig/ adb shell mkdir sdcard/PanelManagement/ adb push E:/ND/Panel/Panel_Switch_Env/env/ohstaging/local_configuration.conf sdcard/PanelManagementConfig adb push E:/ND/Panel/Panel_Switch_Env/env/ohstaging/local_configuration.conf sdcard/PanelManagement/;; 4) adb shell rm -r sdcard/PanelManagementConfig/ adb shell rm -r sdcard/PanelManagement/ adb shell mkdir sdcard/PanelManagementConfig/ adb shell mkdir sdcard/PanelManagement/ adb push E:/ND/Panel/Panel_Switch_Env/env/prod/local_configuration.conf sdcard/PanelManagementConfig adb push E:/ND/Panel/Panel_Switch_Env/env/prod/local_configuration.conf sdcard/PanelManagement/;; *) echo "请输入1到5中的一个";; esac echo "清理环境中" adb root adb shell rm -r data/data/com.nd.promethean.mdmagent/files/.PanelManagementCompat echo "重启设备中" adb reboot;; 1-12) #重启 adb reboot;; 1-13) #关机 adb shell reboot -p;; 1-14) #查看panel任务 adb shell dumpsys jobscheduler com.nd.promethean.mdmagent ;; 1-15) #查看panel 序列号 adb shell getprop ro.serialno;; 1-16) #AP7B 修改序列号 adb disconnect 192.168.84.110 adb disconnect 192.168.84.149 adb disconnect 192.168.84.152 echo -e "已经断开所有panel设备\n" adb connect 192.168.84.150:5555 adb shell am startservice -n com.xbh.factory.menu/.app.TvMenuWindowManagerService -e com.xbh.factory.menu.commmand com.xbh.factory.menu.commmand.factory_menu;; 1-17) #设备录屏(显示触摸点击-t, 文件在e:/git 下) scrcpy -t -r 设备Scrcpy录屏.mp4;; 1-18) #设备设置和移除代理 echo ' 1;设置代理 2: 移除代理 ' read -p "请输入你的选项(1/2):" type if (( $type == 1)); then adb shell settings put global http_proxy 192.168.84.94:1080 elif (( $type == 2)); then adb shell settings delete global http_proxy adb shell settings delete global global_http_proxy_host adb shell settings delete global global_http_proxy_port adb reboot fi;; 2-1) #获取登录token env_init;; 2-2) #从https://rootsh.com/?v=www.bccto.cc申请临时邮箱注册普米账号 env_init read -p "请输入要注册的邮箱:" email familyName="chenrj" domain=${email#*@} #删除指定字符@前面的所有字符,获得域名 givenName=${email%%@*} echo "默认值:登录密码为Jin_111111,国家为美国,语言为英语,job=Teacher" api="/identity/register" res=$(curl $envUrl$api \ -H "x-api-key: $apiKey_pm" \ -H "content-type: application/json; charset=UTF-8" \ -d \ '{"email":"'$email'","password":"Jin_111111","familyName":"'$domain'","givenName":"'$givenName'","countryCode":"US","languageCode":"en","marketingOptIn":false,"acceptEULA":true,"jobTitle":"Teacher"}') echo $res sleep 3s #以便保证收到邮件 echo -e "\n-------获取指定注册验证邮件索引名eml---------" res=$(curl 'https://rootsh.com/getmail' \ -d \ 'mail='$email'&time=0&_=999991623227937233') #echo $res res=${res#*'"Please verify your account","'} #删除全部指定字符"Please verify your account","以及前面的内容 res=${res:22} ##删除最前面22位字符 res=${res//'.eml'/'.eml###'} #把.eml全部替换为.eml### eml=${res%%'###'*} #删除指定字符###以及后面的内容 echo "eml= "$eml echo -e "\n-------从具体的邮件内容里检索出具体的注册验证码:----------" #aa="https://rootsh.com/win/bbb2(a)www.bccto.cc/" aa="https://rootsh.com/win/$givenName(a)$domain/" res=$(curl $aa$eml \ -H 'accept-language: zh-CN,zh;q=0.9' ) #echo $res res=${res#*'verification='} #删除指定字符verification=前面的内容 code=${res%%'">'*} #删除指定字符">后面的内容, 以便只留下最后的六位code echo "注册验证码= "$code echo -e "\n-------验证注册码完成账号的注册:----------" api="/identity/register/confirm" res=$(curl $envUrl$api \ -H "x-api-key: $apiKey_pm" \ -H "content-type: application/json; charset=UTF-8" \ -d \ '{"code":"'$code'","email":"'$email'"}') echo $res;; 2-3) #注册第三方微软组织账号 echo "获取portal.azure的登录token: " echo '{"extensionName":"Microsoft_AAD_IAM","resourceName":"microsoft.graph","tenant":"bdba3fe4-194a-4c9b-8d1f-d9bf1ddfc556","portalAuthorization":"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","altPortalAuthorization":"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"}' \ | curl -i -X POST \ -H 'content-type: application/json' \ -H 'cookie: browserId=ae26b537-8c8a-4413-a4a3-d12ac3460667; portalId=ae26b537-8c8a-4413-a4a3-d12ac3460667' \ -d @- "https://portal.azure.com/api/DelegationToken?feature.cacheextensionapp=true&feature.internalgraphapiversion=true&feature.tokencaching=true" > aa.log data=$(cat aa.log) echo "-------------------------------" idToekn=${data#*'"authHeader":"'} #删除token值前面的内容 idToekn=${idToekn%%'","expiresInMs"'*} #删除token值前面的内容 echo "登录token=: "$idToekn #获得最后的idToekn参数值 echo -e "\n开始创建新用户:" read -p "请输入姓,例如zz: " surname read -p "请输入名,例如1: " givenName displayName=$surname$givenName mailNickname=$surname$givenName userPrincipalName=$mailNickname"@chenrjtest.onmicrosoft.com" echo "初始密码为Jin_111111" res=$(curl 'https://graph.microsoft.com/v1.0/users/' \ -H "Authorization: $idToekn" \ -H "Content-Type: application/json" \ -d \ '{"accountEnabled":true,"displayName":"'$displayName'","mailNickname":"'$mailNickname'","passwordProfile":{"password":"Jin_111111","forceChangePasswordNextSignIn":true},"userPrincipalName":"'$userPrincipalName'","givenName":"'$givenName'","surname":"'$surname'"}') echo $res;; 2-4) #新panel checkin env_init typeList if (( $type == 1 )); then #单个checkin api="/org-support/graphql" read -p "请输入serialNumber(例如OWEN-J9HL9E9999999):" serialNumber read -p "请输入panelName(不输入默认为SN):" panelName read -p "请输入要同步enroll 的组织id(不输入默认为public组织):" orgid echo "新panel checkin:" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "x-api-key: $apiKey_os" \ -H "Authorization: Bearer $Authorization" \ -d \ '{"query":"mutation{addNewPanel(request:{orgId: \"'$orgid'\"\n panelName: \"'$panelName'\"\n serialNumber: \"'$serialNumber'\"}){serialNumber,name,orgName}}"}') echo $res elif (( $type == 2 )); then #批量checkin read -p "请输入serialNumber 的固定前14位(例如BATCH-J9HL9E99):" sn13 read -p "请输入最小serialNumber 的后5位(例如90000,也是起始位):" sn5 read -p "请输入批量创建的个数:" number read -p "请输入要并发执行数,例如10:" run max=$sn5+number api="/org-support/graphql" for (( j=0; j < $run; j++ )) #设置并发 do { for (( i=$sn5+j; i < max; i+=$run )) do { sn="$sn13$i" echo "------------------------------" echo "并行"$j"-----操作对象: "$sn res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "x-api-key: $apiKey_os" \ -H "Authorization: Bearer $Authorization" \ -d \ '{"query":"mutation{addNewPanel(request:{orgId: \"\"\n panelName: \"\"\n serialNumber: \"'$sn'\"}){serialNumber,name,orgName}}"}') echo $res } done }& done fi;; 2-5) #panel enroll env_init echo ' enroll方式: 1: 单个enroll: 通过PM 2: 单个enroll: 通过OS 3: 批量enroll: 通过PM(主,速度快) 4: 批量enroll: 通过OS ' read -p "请选择enroll方式(1/2/3/4):" type if (( $type == 1 )); then read -p "输入要enroll的序列号,例如75W25-J7HL1E0040001: " sn read -p "输入要enroll的panelName, 例如111-149: " panelName read -p "输入到enroll 到的组织id: " orgId api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -H "x-auth-organization-id: $orgId" \ -d \ '{"query": "mutation{enroll(input: [{panelName: \"'$panelName'\",serialNumber: \"'$sn'\"}]){serialNumber,panelName,enrolled}}"}') echo $res elif (( $type == 2 )); then read -p "输入要注册的序列号, 例如75W25-J7HL1E0040001: " sn read -p "输入要注册的panelName, 例如111-149: " panelName read -p "输入要注册到的组织id, 例如46b76d1d-e98c-d483-1a1e-599071307fbe: " orgId api="/org-support/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_os" \ -d \ '{"query":"mutation{enrollPanel(request:{ serialNumber: \"'$sn'\" \n orgId: \"'$orgId'\" \n panelName: \"'$panelName'\" \n notes: \"\"}){serialNumber,orgName \n}}"}') echo $res elif (( $type == 3 )); then read -p "输入到enroll 到的组织id: " orgId read -p "输入要获取的数量: " number read -p "输入要搜索的panel 关键词: " searchKey echo -e "\n获取public批量序列号......." api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -H "x-auth-organization-id: $org_public" \ -d \ '{"query":"query{Panels(searchPanelsInput:{pageSize: '$number' \n offset: 0 \n sortField: serialNumber \n sortType: ASC \n searchFilter:{model: [] \n mainboardFirmware: [] \n siteId: [] \n deviceManagements: [] \n panelName: \"'$searchKey'\" \n thingName: \"'$searchKey'\" \n serialNumbers: [] \n tagGroups: [] \n }}){totalCount \n panels{serialNumber}}}"}') res=${res#*'"panels":[{'} #删除包含指定关键词前面的所有字符 res=${res%%'}]}}}'*} #删除包含指定关键词后面的所有字符 res=${res//'"serialNumber":'} #删除所有指定关键词 res=${res//'},{'/','} #字符替换 res=${res//'"'/'\"'} #字符替换 echo -e "\n运用字符串和数组之间的转换把具体的序列号值赋给panelName和panelName变量以便enroll需要......" array=(${res//,/ }) sns="" for (( i=0; i < ${#array[@]}; i++ )) do { sn=$(echo '{panelName:'${array[i]}',serialNumber: '${array[i]}'},') sns+=$sn } done sns=${sns:0:-1} #删除最后的字符, echo $sns echo -e "\n开始enroll......" echo '{"query": "mutation{enroll(input: ['$sns']){serialNumber,panelName,enrolled}}"}' \ | curl -i -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -H "x-auth-organization-id: $orgId" \ -d @- $envUrl$api > aa.log res=$(cat aa.log) echo $res elif (( $type == 4 )); then read -p "输入到enroll 到的组织id: " orgId read -p "输入要获取的数量: " number read -p "输入要搜索的panel 关键词: " searchKey echo -e "\n获取public批量序列号......." api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -H "x-auth-organization-id: $org_public" \ -d \ '{"query":"query{Panels(searchPanelsInput:{pageSize: '$number' \n offset: 0 \n sortField: serialNumber \n sortType: ASC \n searchFilter:{model: [] \n mainboardFirmware: [] \n siteId: [] \n deviceManagements: [] \n panelName: \"'$searchKey'\" \n thingName: \"'$searchKey'\" \n serialNumbers: [] \n tagGroups: [] \n }}){totalCount \n panels{serialNumber}}}"}') res=${res#*'"panels":[{'} #删除包含指定关键词前面的所有字符 res=${res%%'}]}}}'*} #删除包含指定关键词后面的所有字符 res=${res//'"serialNumber":'} #删除所有指定关键词 res=${res//'},{'/','} #字符替换 res=${res//'"'} #删除所有指定关键词 echo "要enroll 的sns: "$res echo -e "\n开始enroll......" array=(${res//,/ }) api="/org-support/graphql" for (( i=0; i < ${#array[@]}; i++ )) do { sn=$(echo ${array[i]}) echo "操作对象: "$sn res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "x-api-key: $apiKey_os" \ -H "Authorization: Bearer $Authorization" \ -d \ '{"query":"mutation{enrollPanel(request:{ serialNumber: \"'$sn'\" \n orgId: \"'$orgId'\" \n panelName: \"\" \n notes: \"\"}){serialNumber,orgName \n}}"}') echo $res }& #设置多进程并发提高执行速度 done fi;; 2-6) #panel tranfer env_init typeList if (( $type == 1 )); then #单个transfer api="/org-support/graphql" read -p "请输入serialNumber(例如OWEN-J9HL9E9999901):" serialNumber read -p "请输入原先组织id:" srcOrgId read -p "请输入目的组织id:" dstOrgId echo "操作对象: "$serialNumber res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_os" \ -d \ '{"query":"mutation{transferPanel(request:{srcOrgId: \"'$srcOrgId'\" \n dstOrgId: \"'$dstOrgId'\" \n serialNumber: \"'$serialNumber'\" \n panelName: \"\" \n notes:\"\" }) {serialNumber,name,orgName,orgId}}"}') echo $res elif (( $type == 2 )); then #批量transfer read -p "请输入原先组织id:" srcOrgId read -p "请输入目的组织id:" dstOrgId read -p "输入要搜索的panel 关键词(例如AAAA-): " searchKey api="/mdm-portal/graphql" echo "查询要操作的原先组织的panels 列表:" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-auth-organization-id: $srcOrgId" \ -H "x-api-key: $apiKey_pm" \ -d \ '{"query":"query{Panels(searchPanelsInput:{pageSize: 10000 \n offset: 0 \n sortField: name \n sortType: ASC \n searchFilter:{model: [] \n mainboardFirmware: [] \n siteId: [] \ndeviceManagements: [] \n panelName: \"'$searchKey'\" \n thingName: \"'$searchKey'\" \n serialNumbers: [] \n tagGroups: []}}){totalCount,panels{serialNumber}}}"}') panelList=$(echo $res) panelMin=${panelList#*'"Panels":{'} #panelList参数值字符串中删除指定字符"Panels":{前面的内容(包括指定字符) panelMin=${panelMin%%',{"serialNumber"'*} #panelMin参数值字符串中删除指定字符,{"serialNumber"后面的内容(包括指定字符) panelMin=$(echo $panelMin"...") #在panelMin参数字符串最后面补充。。。 echo "原始组织最小的相关序列号是:" $panelMin read -p "请输入serialNumber 的固定前几位(例如AAAA-J7HL1E00):" sn1 read -p "请输入serialNumber 的变动后几位(例如10000,也是起始位):" sn2 read -p "请输入批量操作的个数:" number max=$sn2+number echo "panel 批量transfer:" api="/org-support/graphql" for (( i=$sn2; i < max; i++ )) do { sn="$sn1$i" result=$(echo $panelList | grep "$sn") # "剔除没有在这个组织的panels: " if [[ "$result" != "" ]];then verify="panel 在这个组织里" echo "------------------------------" echo "操作对象: "$sn":符合要求,执行" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_os" \ -d \ '{"query":"mutation{transferPanel(request:{srcOrgId: \"'$srcOrgId'\" \n dstOrgId: \"'$dstOrgId'\" \n serialNumber: \"'$sn'\" \n panelName: \"\" \n notes:\"\" }) {serialNumber,name,orgName,orgId}}"}') echo $res else verify=":不在这个组织里,剔除不执行" echo "------------------------------" echo "操作对象: "$sn$verify continue fi }& done else echo "请输入正确的环境。" fi;; 2-7) #panel manage site env_init echo ' 操作类型列表: 1: 单个 2: 批量(速度快但精确度不高) 3:批量分配并且剔除已分配的数据(速度中且精确度高) ' read -p "请选择操作类型:" type if (( $type == 1 )); then #panel 单次manage site read -p "请输入serialNumber(例如OWEN-J9HL9E9999901-env-dev):" serialNumbers read -p "请输入目的site id:" siteId echo "-----------------------------------------------" echo "操作对象: "$serialNumbers api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -d \ '{"query":"mutation {movePanelsToSites(updatePanelSiteInputs: {operation: update \n updateAll: true \n siteId: \"'$siteId'\" \n serialNumbers: [\"'$serialNumbers'\"]}){success}}"}') echo $res elif (( $type == 2 )); then #panel 批量manage site 方法1(速度快,精确度不高) read -p "请输入serialNumber 的固定前几位(例如Batch):" sn1 read -p "请输入serialNumber 的变动后几位(例如300002,也是起始位):" sn2 read -p "请输入批量更新的个数:" number read -p "请输入目的site id:" siteId max=$sn2+number for (( i=$sn2; i < max; i++ )); do serialNumber='\"'$sn1$i$stuff'\"' serialNumbers=$serialNumber","$serialNumbers done serialNumbers=${serialNumbers::-1} echo "-----------------------------------------------" echo "操作对象: "$serialNumbers api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -d \ '{"query":"mutation {movePanelsToSites(updatePanelSiteInputs: {operation: update \n updateAll: true \n siteId: \"'$siteId'\" \n serialNumbers: ['$serialNumbers']}){success}}"}') echo $res elif (( $type == 3 )); then #批量分配并且剔除已分配的数据(速度中但精确度高) echo "查询site 为空的panels:" # 查询site 为空的panels read -p "要查询的组织id为: " orgid read -p "要查询的搜索关键词为: " searchKey api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-auth-organization-id: $orgid" \ -H "x-api-key: $apiKey_pm" \ -d \ '{"query":"query{Panels(searchPanelsInput:{pageSize: 10000 \n offset: 0 \n sortField: name \n sortType: ASC \n searchFilter:{model: [] \n mainboardFirmware: [] \n siteId: [\"\"] \ndeviceManagements: [] \n panelName: \"'$searchKey'\" \n serialNumbers: [] \n tagGroups: []}}){totalCount,panels{serialNumber}}}"}') panelList=$(echo $res) panelMin=${panelList#*'"Panels":{'} #panelList参数值字符串中删除指定字符"Panels":{前面的内容(包括指定字符) panelMin=${panelMin%%',{"serialNumber"'*} #panelMin参数值字符串中删除指定字符,{"serialNumber"后面的内容(包括指定字符) panelMin=$(echo $panelMin"...") #在panelMin参数字符串最后面补充。。。 echo $panelMin echo "对未分配site的panel进行分配到特定site 操作:" #对未分配site的panel进行分配site 操作 read -p "请输入serialNumber 的固定前几位(例如Batch):" sn1 read -p "请输入serialNumber 的变动后几位(例如300002,也是起始位):" sn2 read -p "请输入要操作的panels 数量:" number read -p "请输入目的siteId(例如2cbc7ea4-15c6-ca62-e55e-b944797a480f):" siteId max=$sn2+number echo "剔除已分配site的panels:" for (( i=$sn2; i < max; i++ )); do serialNumber=$sn1$i$stuff result=$(echo $panelList | grep "${serialNumber}") if [[ "$result" != "" ]];then verify="未分配site" serialNumber='\"'$sn1$i$stuff'\"' serialNumbers=$serialNumber","$serialNumbers else verify="已分配site" echo $serialNumber"验证结果: "$verify",剔除不执行" continue fi done echo "-----------------------------------------------" echo "操作对象: "$serialNumbers echo "开始执行批量分配site:" api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-auth-organization-id: dcb7ced2-f3a2-4423-2cc4-164ffb02fc31" \ -H "x-api-key: $apiKey_pm" \ -d \ '{"query":"mutation {movePanelsToSites(updatePanelSiteInputs: {operation: update \n updateAll: true \n siteId: \"'$siteId'\" \n serialNumbers: ['$serialNumbers']}){success}}"}') echo $res else echo "请输入正确的环境。" fi;; 2-8) #显示组织列表和sites 列表 env_init echo -e "\n显示组织列表: " #组织列表 read -p "需要搜索的关键词:" searchString api="/org-support/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_os" \ -d \ '{"query":"query{searchOrgs(searchRequest: {pageNumber: 0 \n pageSize: 50 \n sortDirection: ASC \n sortField: name \n searchString: \"'$searchString'\"}){orgs{id,name,prn}}}"}') res=${res//'{"data":{"searchOrgs":{"orgs":[{'} #删除{"data":{"searchOrgs":{"orgs":[{ res=${res//'"'} # },{ #删除" res=${res//'}]}}}'} # },{ #删除}]}}} res=${res//'},{'/'\n'} # 把},{ 替换为\n res=${res//','/'----->'} # 把, 替换为-----> res=${res//'----->:prn'/'--------------->'} # 把----->:prn替换为---------------> echo -e $res echo -e "\n显示sites列表: " #sites 列表 read -p "输入组织的orgprn: " orgPrn read -p "需要搜索的关键词:" searchString api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -d \ '{"query":"query{searchSites(searchRequest: {pageNumber: 0 \n pageSize: 25 \n parentOrgPrn: \"'$orgPrn'\" \n searchString: \"'$searchString'\" \n sortDirection: ASC \n sortField: name \n }){sites {id,name,panelCount}}}"}') res=${res//'{"data":{"searchSites":{"sites":[{'} #删除{"data":{"searchOrgs":{"orgs":[{ res=${res//'"'} # },{ #删除" res=${res//'}]}}}'} # },{ #删除}]}}} res=${res//'},{'/'\n'} # 把},{ 替换为\n res=${res//','/'----->'} # 把, 替换为-----> echo -e $res;; #-e:把\n 变为换行符 2-9) #显示指定org/site/search下的panels列表 env_init echo -e "\n显示指定org下的的panels列表: " read -p "输入组织id, 例如46b76d1d-e98c-d483-1a1e-599071307fbe: " orgId read -p "输入siteId(不输入代表没有分配site,例如26b95df7-f4e5-a3b2-8dab-1baea4116045: " siteId read -p "输入搜索关键词: " searchKey api="/mdm-portal/graphql" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -H "x-auth-organization-id: $orgId" \ -d \ '{"query":"query{Panels(searchPanelsInput:{pageSize: 10000 \n offset: 0 \n sortField: name \n sortType: ASC \n searchFilter:{model: [] \n mainboardFirmware: [] \n siteId: [\"'$siteId'\"] \n deviceManagements: [] \n panelName: \"'$searchKey'\" \n thingName: \"'$searchKey'\" \n serialNumbers: [] \n tagGroups: [] \n }}){totalCount \n panels{serialNumber}}}"}') #res=${res//'{"data":{"Panels":{"panels":['} #删除指定字符 res=${res//'},{"serialNumber":'/','} #字符替换 res=${res//'"serialNumber":'/'"serialNumber":\n'} #字符替换 panels=${res//'}]}}}'} #删除指定字符 echo -e $panels;; 2-10) #添加新的radix QaFirmware panel版本 env_init api="/integration/graphql" read -p "请输入radix版本(例如0.0.3):" bundleVersion read -p "请输入白板型号(例如AP7B):" panelModel read -p "请输入要加入到QaFirmware的firmware 版本(例如4.3.0.7):" panelVersion echo "添加radix新QaFirmware:" res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "x-api-key: $apiKey_integration" \ -H "Authorization: Bearer $Authorization" \ -d \ '{"query":"mutation{\n qaPanelBundleVersion(request:{\n bundleId: \"'$bundleId'\"\n bundleVersion: \"'$bundleVersion'\"\n panelModel: \"'$panelModel'\" \n panelVersion: \"'$panelVersion'\" \n }){id}}"}') echo $res;; 2-11) #账号重置eula状态 env_init api="/profile/reset-eula" read -p '请输入要在重置的账号emails(支持批量例如chenrj@nd.com.cn): ' emails res=$(curl $envUrl$api \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $Authorization" \ -H "x-api-key: $apiKey_pm" \ -d \ '{"emails": ["'$emails'"]}') echo $res;; 3-1) #获取登录的设备列表 env_init #获取登录的设备列表 echo -e "\n获取登录的设备列表: " api="/identity/device/linked" res=$(curl $envUrl$api \ -H "content-type: application/json; charset=UTF-8" \ -H "x-api-key: $apiKey_pm" \ -H "Authorization: Bearer $Authorization") res=${res//'{"profileId":'/'\n{"profileId":'} res=${res//'"id"'/'\n----"id"'} echo -e $res;; 3-2) #登录新设备 env_init #获取登录的设备列表 echo -e "\n获取登录的设备列表: " api="/identity/device/linked" res=$(curl $envUrl$api \ -H "content-type: application/json; charset=UTF-8" \ -H "x-api-key: $apiKey_pm" \ -H "Authorization: Bearer $Authorization") res=${res//'{"profileId":'/'\n{"profileId":'} echo -e $res # 设备登录 echo -e "\n" read -p "输入要登录的序列号(不输入代表不登录新设备单纯获取token,设备序列号需要已经在环境里入库且如果有后缀需要加上),例如75W25-J7HL1E0040001-env-dev:" deviceId api="/identity/login" res=$(curl -i -X POST $envUrl$api \ -H "Content-Type:application/json; charset=UTF-8" \ -H "x-api-key:$apiKey_token" \ -H "x-device-id: $deviceId" \ -d \ '{ "email":"'$email'" , "password":"'$password'" }' ) token1=${res#*IdToken} token2=${token1:3} token3=${token2%%user_sub*} Authorization=${token3::-4} echo "设备登录token 为:"$Authorization #获取登录的设备列表 echo -e "\n获取登录的设备列表: " api="/identity/device/linked" res=$(curl $envUrl$api \ -H "content-type: application/json; charset=UTF-8" \ -H "x-api-key: $apiKey_pm" \ -H "Authorization: Bearer $Authorization") res=${res//'{"profileId":'/'\n{"profileId":'} echo -e $res;; 3-3) #登出设备 env_init #获取登录的设备列表 echo -e "\n获取登录的设备列表: " api="/identity/device/linked" res=$(curl $envUrl$api \ -H "content-type: application/json; charset=UTF-8" \ -H "x-api-key: $apiKey_pm" \ -H "Authorization: Bearer $Authorization") res=${res//'{"profileId":'/'\n{"profileId":'} echo -e $res echo -e "\n" echo -e "\n设备登出: " #设备登出 read -p "请输入要登出的设备, 例如75W25-J7HL1E0040001-env-dev:panel-identity-app: " deviceId api="/identity/device/linked" res=$(curl $envUrl$api \ -X "DELETE" \ -H "authorization: Bearer $Authorization" \ -H "content-type: application/json; charset=UTF-8" \ -H "x-api-key: $apiKey_pm" \ -d \ '{"id":"'$deviceId'"}') echo $res #获取登录的设备列表 echo -e "\n获取登录的设备列表: " api="/identity/device/linked" res=$(curl $envUrl$api \ -H "content-type: application/json; charset=UTF-8" \ -H "x-api-key: $apiKey_pm" \ -H "Authorization: Bearer $Authorization") res=${res//'{"profileId":'/'\n{"profileId":'} echo -e $res;; 3-4) #idp:更新壁纸 #get_authorization_token envUrl="https://devapi.prometheanproduct.com" api="/identity/login" apiKey_token="b0p31d5rm8ifd93132cfolmsa01yc60u4nd79btg" echo "获取登录Token:" read -p "输入登录的账号: " email read -p "输入登录密码: " password res=$(curl -i -X POST $envUrl$api \ -H "Content-Type:application/json" \ -H "x-api-key:$apiKey_token" \ -d \ '{ "email":"'$email'" , "password":"'$password'" }' ) token1=${res#*IdToken} token2=${token1:3} token3=${token2%%user_sub*} Authorization=${token3::-4} echo -e "登录token: $Authorization\n" echo -e "更新壁纸:" echo -e "图片来源链接例如: http://img.jj20.com/up/allimg/1114/062621104051/210626104051-1-1200.jpg\n" read -p "输入壁纸来源链接: " wallpaperUrl res=$(curl --request POST \ --url https://devapi.prometheanproduct.com/profile/graphql \ --header "Content-Type: application/json" \ --header "authorization: Bearer $Authorization" \ --header "x-api-key: b0p31d5rm8ifd93132cfolmsa01yc60u4nd79btg" \ --data '{"query":"mutation {\n updateUserProfile(userProfileInput: {\n panelPreference: {\n wallpaperUrl: \"'$wallpaperUrl'\"\n }\n }) {\n panelPreference {\n wallpaperUrl\n }\n }\n}"}') echo $res;; 3-5) #idp:NFC echo ' 1;NFC card--create/assign 2: NFC card--search 3:NFC card--lock 4:NFC card--unlock 5:NFC card--delete ' read -p "请输入你的选项:" type env_init nfcTagId="17689406280" #默认一个nfcTagId if (( $type == 1)); then #NFC card--create/assign curl --request POST \ --url $envUrl/identity/nfc/create \ --header "Authorization: Bearer $Authorization" \ --header "Content-Type: application/json" \ --header "x-api-key: $apiKey_token" \ --data '{ "nfcTagId": "'$nfcTagId'" }' curl --request POST \ --url $envUrl/identity/nfc/assigned \ --header "Authorization: Bearer $Authorization" \ --header "Content-Type: application/json" \ --header "x-api-key: $apiKey_token" \ --data '{ "nfcTagId": "'$nfcTagId'" }' elif (( $type == 2)); then #NFC card--search curl --request GET \ --url $envUrl/identity/nfc/assigned \ --header "Authorization: Bearer $Authorization" \ --header "x-api-key: $apiKey_token" elif (( $type == 3)); then #NFC card--lock curl --request POST \ --url $envUrl/identity/nfc/update \ --header "Authorization: Bearer $Authorization" \ --header "Content-Type: application/json" \ --header "x-api-key: $apiKey_token" \ --data '{ "nfcTagId": "'$nfcTagId'", "frozen": true }' elif (( $type == 4)); then #NFC card--unlock curl --request POST \ --url $envUrl/identity/nfc/update \ --header "Authorization: Bearer $Authorization" \ --header "Content-Type: application/json" \ --header "x-api-key: $apiKey_token" \ --data '{ "nfcTagId": "'$nfcTagId'", "frozen": false }' elif (( $type == 5)); then #NFC card--delete curl --request DELETE \ --url $envUrl/identity/nfc/assigned \ --header "Authorization: Bearer $Authorization" \ --header "Content-Type: application/json" \ --header "x-api-key: $apiKey_token" \ --data '{ "nfcTagId": "'$nfcTagId'" }' fi;; *) echo "请输入一个正确的数字" esac echo "运行完成" echo "------------------------------------------------------------------------" } #================================================================================================================================================================================================================================================================= menuList run done #字符串: # 变量2=${变量1//'查找值'/'替换值'} #字符替换:一个'/'表示替换第一个'//'表示替换所有; 例如b=${a//'4+4'/'5+6'}-->把a变量中的4+4字符全部替换成5+6并赋给b变量 # 变量2=${变量1//'指定字符'} #删除指定字符:一个'/'表示删除第一个'//'表示删除所有; 例如b=${a/12} -->从a变量中删除指定字符12并赋给b变量 # 变量2=$(Echo $变量1 | sed 's/指定字符//g') #删除指定字符:例如b=$(Echo $a | sed 's/-//')-->从a变量中删除指定字符-并赋给b变量 # 变量2=$(Echo $变量1 | sed 's/....指定字符..//g') #删除指定字符及前面/后面固定几位:例如b=$(Echo $a | sed 's/..k...//')-->从a变量中删除指定字符k以及k前面2位后面3位的字符并赋给b变量(几位就加几个点) # 变量2=${变量:位数} #删除最首的n位:例如b=${a:2} -->a变量中删除最前面两位数并赋值给b; # 变量2=${变量:0:-位数} #删除最末的n位; 例如b=${a:0:-2}-->a变量中删除最后面两位数并赋值给b # 变量2=${变量1#*'指定字符'} #删除指定字符以及前面的内容:例如data1=${res#*'指定字符'} -->从res变量字符串中删除指定字符前面的内容(包括指定字符)并赋值给data1, # 变量2=${变量1%%'指定字符'*} #删除指定字符以及后面的内容:例如data2=${data1%%'指定字符'*} -->从data1变量中删除指定字符后面的内容(包括指定字符)并赋值给data2, # 变量2=${变量1//'指定字符'/'\n'} echo -e $变量 #换行:1.先把指定字符全部替换为\n, 2.然后使用echo -e 打印出来(-e:把\n 变为换行符) # 变量2=${变量1%%指定字符*} #获取指定字符前面的内容 #curl变量引用: # 顶部head 部分,需要双引号,然后直接使用 $参数 方式; # 中间body 部分,直接使用 '$变量' 的方式; # 底部接口 "变量值" 要写成 \"'$变量' \" #编写格式: # 中文乱码选用UTF-8编码格式 #curl报错Argument list too long参数过长解决方式: #使用 @- 从标准输入中获取数据。利用echo输出到标准输入,再利用管道重定向输入到curl的-d参数中。 #echo '{"userhname":"xxx","pwd":"'$pwd'","nickname":"test"}' \ #| curl -i -X POST \ # -H 'Content-Type:application/json' \ # -H 'x-api-key:fdfsgdgdhfhfjjj' \ # -d @- "http://api.com/yourapi" > aa.log #res=$(cat aa.log) #echo $res
声明 欢迎转载,但请保留文章原始出处:) 博客园:https://www.cnblogs.com/chenxiaomeng/
如出现转载未声明 将追究法律责任~谢谢合作
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具