在Ubuntu/Orange Pi 5环境下通过终端获取Kiosk模式Chromium的已打开标签页(PowerShell脚本开发场景)
在Ubuntu/Orange Pi 5环境下通过终端获取Kiosk模式Chromium的已打开标签页(PowerShell脚本开发场景)
看起来你现在卡在了通过终端准确获取Kiosk模式下Chromium当前打开的标签页这一步,而且想优化现有的PowerShell脚本,让它更像保活工具而非粗暴重启。我结合你的场景给你分点梳理解决方案和优化建议:
一、核心问题:获取Chromium当前打开的标签页(替代BroTab和Session文件方案)
你的核心需求是判断当前标签页是否符合配置,避免不必要的重启。之前尝试的Session文件读取存在更新不及时的问题,这里给你两个更可靠的方案:
1. 推荐:利用Chromium远程调试接口(DevTools Protocol)
Chromium支持通过远程调试端口暴露实时标签页信息,这是最准确的方式,无论Chromium是手动还是终端启动都能正常工作:
- 步骤1:修改Chromium启动命令,添加远程调试端口参数:
$chrome = "DISPLAY=:0 chromium-browser $link_string --kiosk --disable-session-crashed-bubble --disable-infobars --remote-debugging-port=9222 &> /dev/null &"
- 步骤2:在PowerShell中调用接口获取标签页:
function Get-ChromiumActiveTabs { param([string]$Ip) try { # 调用远程调试接口获取所有标签页JSON数据 $tabData = Invoke-RestMethod -Uri "http://$Ip:9222/json" -ErrorAction Stop # 提取所有页面类型标签页的URL return $tabData | Where-Object { $_.type -eq "page" } | Select-Object -ExpandProperty url } catch { Write-Error "无法获取$Ip的Chromium标签页:$_" return @() } } # 在主循环中使用该函数 $currentTabs = Get-ChromiumActiveTabs -Ip $ip $expectedTabs = $link_string -split "\s+" | ForEach-Object { $_.Trim() } # 检查所有预期URL是否都在当前标签页中 $needsRestart = $false foreach ($url in $expectedTabs) { if ($currentTabs -notcontains $url) { $needsRestart = $true break } } if ($needsRestart) { Write-Host "$ip的标签页不匹配,执行重启..." Invoke-PiCommand -Ip $ip -Command $exitchrome -SuppressOutput Start-Sleep -Seconds 5 Invoke-PiCommand -Ip $ip -Command $chrome -SuppressOutput } else { Write-Host "$ip的标签页符合要求,跳过重启" }
2. 备选方案:通过进程命令行参数判断(仅适用于固定标签页场景)
如果你的场景是脚本启动固定标签页,没有手动添加标签的需求,可以直接检查Chromium进程的命令行参数:
$chromiumCmd = Invoke-PiCommand -Ip $ip -Command "ps aux | grep chromium-browser | grep -v grep" $needsRestart = -not ($chromiumCmd -match [regex]::Escape($link_string))
这个方案更轻量,但不支持动态标签页的检测。
二、脚本整体优化建议(针对你的需求:函数、错误日志、邮件通知)
1. 重构重复代码为函数,提升可维护性
你提到函数使用有困难,这里给你封装几个核心函数,统一处理SSH执行、错误捕获:
# 通用SSH执行函数,带错误处理 function Invoke-PiCommand { param( [Parameter(Mandatory=$true)][string]$Ip, [Parameter(Mandatory=$true)][string]$Command, [switch]$SuppressOutput ) try { # 捕获标准输出和错误输出 $output = ssh orangepi@$Ip -X $Command 2>&1 if (-not $SuppressOutput) { return $output -join "`n" } } catch { $errorMsg = "在$Ip执行命令失败:`n命令:$Command`n错误:$_" Write-Error $errorMsg # 这里可以调用错误日志/邮件通知函数 Log-Error -Message $errorMsg Send-FailureAlert -Ip $Ip -Message $errorMsg throw $errorMsg # 可选:终止脚本或继续执行 } } # 获取分辨率的函数(用正则替代字符串索引,更可靠) function Get-PiResolution { param([string]$Ip) $xrandrOutput = Invoke-PiCommand -Ip $Ip -Command "xrandr -display :0.0" $resMatch = [regex]::Match($xrandrOutput, '(\d{3,4} x \d{3,4})').Value return $resMatch }
2. 添加错误日志与邮件通知
# 错误日志函数 function Log-Error { param([string]$Message) $logPath = "C:\temp\display_management_errors.log" $logEntry = "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] $Message" Add-Content -Path $logPath -Value $logEntry -Encoding UTF8 } # 邮件通知函数 function Send-FailureAlert { param( [string]$Ip, [string]$Message ) $smtpParams = @{ SmtpServer = "你的SMTP服务器地址" From = "display-monitor@yourdomain.com" To = "admin@yourdomain.com" Subject = "显示终端$Ip异常告警" Body = "异常详情:`n$Message" Port = 587 # 或你的SMTP端口 UseSsl = $true Credential = (Get-Credential -Message "输入SMTP凭据") # 或存储在安全字符串中 } Send-MailMessage @smtpParams -ErrorAction SilentlyContinue }
3. 优化保活与重启逻辑
- 把“每30分钟强制重启”改成“定时检查(比如每5分钟),仅在异常时重启”
- 替换粗暴的
killall -9为温和的终止,避免Session文件损坏:
# 先尝试正常关闭,失败再强制杀死 $exitchrome = "killall chromium-browser &>/dev/null; sleep 3; killall -9 chromium-browser &>/dev/null; exit;"
4. 时间处理优化(支持所有月份的月末更新)
你原来的$Calendar.Day -eq '28'不够通用,改成自动判断当月最后一天:
$isLastDayOfMonth = $Calendar.Day -eq [DateTime]::DaysInMonth($Calendar.Year, $Calendar.Month) if ($isLastDayOfMonth -and $Calendar -gt $updatestart -and $Calendar -lt $updatecutoff) { Write-Host "$ip执行月末系统更新..." Invoke-PiCommand -Ip $ip -Command "sudo apt-get update; sudo apt-get upgrade -y; sudo reboot;" Start-Sleep -Seconds 60 }
三、你提供的原始脚本格式化版本
## SCRIPT TO RERESH AND MANAGE PI BOXES FOR DISPLAYS ## $getr=$null; ## SET VARIABLES TO GET DATES AND FOR SPECIFIC TIMES IN REGARDS TO UPDATES $Calendar = Get-Date $updatestart = Get-Date -Hour 11 -Minute 55 $updatecutoff = Get-Date -Hour 12 -Minute 01 ## SET VARIABLES FOR PI INSTRUCTIONS $exitchrome = "killall -9 chromium-browser &>/dev/null; exit;" ## QUITS BROWSER AND EXITS SCRIPT Get-Content -Path "C:\temp\ip.txt" | Foreach-Object { ## LOOP THROUGH CONTENTS OF TEXT FILE - IP.TXT $textfile = $_; $pos = $textfile.IndexOf("|") ## LOOK FOR PIPE CHARECTER IN TEXT FILE $link_string = $textfile.Substring($pos+1) ## CONTENTS AFTER PIPE CHARECTER $ip = $textfile.Substring(0, $pos) ## CONTENTS BEFORE PIPE CHARECTER echo $ip $chrome = "DISPLAY=:0 chromium-browser " + $link_string + " --kiosk --disable-session-crashed-bubble --disable-infobars &> /dev/null &" ## STARTS BROWSER IN KIOSK MODE ## PLAY CODE## $i = 0 $c = 0 $w = 1 $wb_chk = "cat -e ~/.config/chromium/Default/Sessions/Tabs_* | sed -e 's/\^@/\n/g' -e '/_\/chrome/d' | grep -Po '(http|https)://\K.*' | sort -u" ## CHECK BROWSER FOR OPEN TABS $wb_chk_res = ssh orangepi@"$ip" -X "$wb_chk" | Out-String foreach($url_array in -split $link_string) { $url_array_pos = $url_array.IndexOf("/") ## LOOK FOR SLASH IN VARIABLE $url_array = $url_array.Substring($url_array_pos+2) ## REMOVE CONTENTS AFTER SLASH $i++ foreach($wbl_chk in -split $wb_chk_res) { $w++ if ($wbl_chk -eq $url_array) { $c++ } } } echo "$w websites were checked" echo "There are $c live on the display" echo "$c websites match the $i URLS in the config file" ## PLAY CODE## If ($Calendar.Day -eq '28' -AND $Calendar.TimeOfDay -gt $updatestart.TimeOfDay -AND $Calendar.TimeOfDay -lt $updatecutoff.TimeOfDay) { ## IF END OF THE MONTH, RUN UPDATES ssh -p 222 pi@"$ip" -X "sudo apt-get update; sudo apt-get upgrade -y; sudo reboot;" Start-Sleep -s 60 } ## CHECK DISPLAY RES ## $getr = ssh orangepi@"$ip" -X "xrandr -display :0.0;" | Out-String $res_pos = $getr.IndexOf(",") ## LOOK FOR COMMA IN VARIABLE $getr = $getr.Substring($res_pos+2) ## REMOVE CONTENTS AFTER COMMA $res_pos = $getr.IndexOf(",") ## LOOK FOR COMMA IN VARIABLE $getr = $getr.Substring(0, $res_pos) ## REMOVE CONTENTS BEFORE COMMA $res_pos = $getr.IndexOf(" ") ## LOOK FOR SPACE IN VARIABLE $getr = $getr.Substring($res_pos+1) ## REMOVE CONTENTS BEFORE SPACE $uptime = ssh orangepi@"$ip" -X "awk '{print $1}' /proc/uptime" | Out-String $up_pos = $uptime.IndexOf(" ") ## LOOK FOR SPACE IN VARIABLE $uptime = $uptime.Substring(0,$up_pos) ## CONTENTS BEFORE SPACE echo $uptime echo $getr if ($uptime -lt "1800.00" -Or $getr -ne "1920 x 1080") { echo "Forcing Display Resolution"; ssh orangepi@"$ip" -X "sudo service lightdm restart;" Start-Sleep -s 10; ssh orangepi@"$ip" -X "$chrome"; Start-Sleep -s 10; ssh orangepi@"$ip" -X "$exitchrome"; Start-Sleep -s 10; $getr=$null; } $MATICS = select-string -pattern "xxx.my.leadermes.com" -InputObject $link_string ## LOOK FOR MATICS URL if ($MATICS -ne $null) { $getr = ssh orangepi@"$ip" -X "xrandr -display :0.0;" | Out-String $res_pos = $getr.IndexOf(",") ## LOOK FOR COMMA IN VARIABLE $getr = $getr.Substring($res_pos+2) ## CONTENTS AFTER COMMA $res_pos = $getr.IndexOf(",") ## LOOK FOR COMMA IN VARIABLE $getr = $getr.Substring(0, $res_pos) ## CONTENTS BEFORE COMMA $res_pos = $getr.IndexOf(" ") ## LOOK FOR SPACE IN VARIABLE $getr = $getr.Substring($res_pos+1) ## CONTENTS AFTER SPACE echo "MATICS ON DISPLAY"; ssh orangepi@"$ip" -X "$exitchrome"; ssh orangepi@"$ip" -X "$chrome"; if ($getr -eq "1920 x 1080") { echo "$getr live"; Start-Sleep -s 15 ssh orangepi@"$ip" -X "DISPLAY=:0 xdotool key Return; exit;" Start-Sleep -s 20 ssh orangepi@"$ip" -X "DISPLAY=:0 xdotool key Tab Tab space mousemove 220 60 click 1; exit;" Start-Sleep -s 20 ssh orangepi@"$ip" -X "DISPLAY=:0 xdotool mousemove 1860 180 click 1 mousemove 1920 1080; exit;" $getr=$null; } } else { echo "MATICS IS NOT ON THIS DISPLAY"; ssh orangepi@"$ip" -X "$exitchrome"; ssh orangepi@"$ip" -X "$chrome"; } }
备注:内容来源于stack exchange,提问作者M.Atkinson




