opencode commited on
Commit
a1ec78c
·
1 Parent(s): 9565f33

修正桌面啟動時的 No session for pid:停用 lxpolkit/light-locker autostart

Browse files
Files changed (2) hide show
  1. README.md +2 -0
  2. app.py +79 -1
README.md CHANGED
@@ -53,6 +53,8 @@ OpenCode 在啟動時安裝,並重設使用者層級設定為預設值。
53
  重複的程序會被清掉。
54
  - 桌面裡永遠有一個標題為「共用終端機」的 xterm;把它關掉後看門狗會自動再開一個,
55
  所以固定分頁裡永遠有 1 個可用的圖形終端機視窗(使用者自己另開的终端機不受影響)。
 
 
56
  - 瀏覽器是透過 `/vnc` WebSocket 橋接到同一個桌面,所有裝置看到完全相同、可同時操作的
57
  LXDE 畫面;關掉瀏覽器分頁不會終止桌面,重新整理或重新連線都會接回原畫面。
58
  - 這個分頁是固定的:按它的 `×` 不會刪除分頁,而是重新啟動一份新的桌面
 
53
  重複的程序會被清掉。
54
  - 桌面裡永遠有一個標題為「共用終端機」的 xterm;把它關掉後看門狗會自動再開一個,
55
  所以固定分頁裡永遠有 1 個可用的圖形終端機視窗(使用者自己另開的终端機不受影響)。
56
+ - 容器內沒有 systemd-logind session,因此會自動停用 `lxpolkit` 與 `light-locker`
57
+ autostart,避免桌面啟動時跳出「No session for pid …」的 Error 對話框。
58
  - 瀏覽器是透過 `/vnc` WebSocket 橋接到同一個桌面,所有裝置看到完全相同、可同時操作的
59
  LXDE 畫面;關掉瀏覽器分頁不會終止桌面,重新整理或重新連線都會接回原畫面。
60
  - 這個分頁是固定的:按它的 `×` 不會刪除分頁,而是重新啟動一份新的桌面
app.py CHANGED
@@ -1460,6 +1460,79 @@ class DesktopManager:
1460
  def _term_binary(self):
1461
  return shutil.which("xterm") or shutil.which("lxterminal")
1462
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1463
  def _kill_pids(self, pids, sig=signal.SIGTERM):
1464
  for pid in pids:
1465
  if not self._pid_alive(pid):
@@ -1544,6 +1617,7 @@ class DesktopManager:
1544
  return True
1545
 
1546
  async def _start_session(self) -> bool:
 
1547
  last_error = "找不到 startlxde / lxsession / openbox"
1548
  for launcher in ("startlxde", "lxsession", "openbox"):
1549
  path = shutil.which(launcher)
@@ -1563,6 +1637,8 @@ class DesktopManager:
1563
  if pid:
1564
  self.pids["session"] = pid
1565
  self._log(f"LXDE session 就緒({launcher},pid {pid})")
 
 
1566
  return True
1567
  last_error = f"{launcher} 啟動後立即結束(returncode={proc.poll()})"
1568
  self._log(last_error, logging.WARNING)
@@ -1601,7 +1677,8 @@ class DesktopManager:
1601
  return True
1602
  name = os.path.basename(binary)
1603
  if name == "xterm":
1604
- argv = [binary, "-u8", "-geometry", "110x32+50+50",
 
1605
  "-T", self.TERM_TITLE, "-e", "bash", "--login"]
1606
  else:
1607
  argv = [binary, "--title=" + self.TERM_TITLE, "-e", "bash --login"]
@@ -1633,6 +1710,7 @@ class DesktopManager:
1633
  if not await self._start_vnc():
1634
  return False
1635
  await self._start_term()
 
1636
  self.started_at = time.time()
1637
  if self._healthy():
1638
  self.last_error = ""
 
1460
  def _term_binary(self):
1461
  return shutil.which("xterm") or shutil.which("lxterminal")
1462
 
1463
+ def _prepare_session_config(self):
1464
+ """關掉容器裡必然失敗的 polkit / 螢幕鎖定 autostart,避免出現
1465
+ 「No session for pid …」的 Error 對話框(Xvfb 沒有 logind session)。"""
1466
+ autostart = os.path.join(HOME, ".config", "autostart")
1467
+ try:
1468
+ os.makedirs(autostart, exist_ok=True)
1469
+ for name in ("lxpolkit", "light-locker"):
1470
+ path = os.path.join(autostart, name + ".desktop")
1471
+ content = (
1472
+ "[Desktop Entry]\n"
1473
+ "Type=Application\n"
1474
+ f"Name={name}\n"
1475
+ "Exec=/bin/true\n"
1476
+ "Hidden=true\n"
1477
+ "NoDisplay=true\n"
1478
+ "X-GNOME-Autostart-enabled=false\n"
1479
+ )
1480
+ if not (os.path.isfile(path) and open(path).read() == content):
1481
+ with open(path, "w") as f:
1482
+ f.write(content)
1483
+ except OSError as exc:
1484
+ self._log(f"無法寫入 autostart 覆寫:{exc}", logging.WARNING)
1485
+
1486
+ system_conf = "/etc/xdg/lxsession/LXDE/desktop.conf"
1487
+ user_conf = os.path.join(HOME, ".config", "lxsession", "LXDE", "desktop.conf")
1488
+ source = user_conf if os.path.isfile(user_conf) else system_conf
1489
+ try:
1490
+ if not os.path.isfile(source):
1491
+ return
1492
+ with open(source) as f:
1493
+ lines = f.read().splitlines()
1494
+ changed = False
1495
+ out = []
1496
+ for line in lines:
1497
+ if line.startswith("polkit/command=") and line != "polkit/command=":
1498
+ line = "polkit/command="
1499
+ changed = True
1500
+ elif line.startswith("lock_manager/command=") and line != "lock_manager/command=":
1501
+ line = "lock_manager/command="
1502
+ changed = True
1503
+ out.append(line)
1504
+ if changed or source != user_conf:
1505
+ os.makedirs(os.path.dirname(user_conf), exist_ok=True)
1506
+ with open(user_conf, "w") as f:
1507
+ f.write("\n".join(out) + "\n")
1508
+ except OSError as exc:
1509
+ self._log(f"無法寫入 lxsession 設定:{exc}", logging.WARNING)
1510
+
1511
+ def _suppress_session_popups(self):
1512
+ """保險:如果 lxpolkit / light-locker 還是被拉起來,直接關掉(不影響桌面)。"""
1513
+ pids = []
1514
+ try:
1515
+ entries = os.listdir("/proc")
1516
+ except OSError:
1517
+ return
1518
+ for entry in entries:
1519
+ if not entry.isdigit():
1520
+ continue
1521
+ pid = int(entry)
1522
+ if pid == os.getpid():
1523
+ continue
1524
+ cmd = self._cmdline(pid)
1525
+ if not cmd:
1526
+ continue
1527
+ low = cmd.lower()
1528
+ if not any(name in low for name in ("lxpolkit", "light-locker")):
1529
+ continue
1530
+ if DESKTOP_DISPLAY in cmd or self._has_display(pid):
1531
+ pids.append(pid)
1532
+ if pids:
1533
+ self._log(f"關閉容器內無效的 session 元件:{pids}")
1534
+ self._kill_pids(pids, signal.SIGKILL)
1535
+
1536
  def _kill_pids(self, pids, sig=signal.SIGTERM):
1537
  for pid in pids:
1538
  if not self._pid_alive(pid):
 
1617
  return True
1618
 
1619
  async def _start_session(self) -> bool:
1620
+ self._prepare_session_config()
1621
  last_error = "找不到 startlxde / lxsession / openbox"
1622
  for launcher in ("startlxde", "lxsession", "openbox"):
1623
  path = shutil.which(launcher)
 
1637
  if pid:
1638
  self.pids["session"] = pid
1639
  self._log(f"LXDE session 就緒({launcher},pid {pid})")
1640
+ await asyncio.sleep(0.5)
1641
+ await asyncio.to_thread(self._suppress_session_popups)
1642
  return True
1643
  last_error = f"{launcher} 啟動後立即結束(returncode={proc.poll()})"
1644
  self._log(last_error, logging.WARNING)
 
1677
  return True
1678
  name = os.path.basename(binary)
1679
  if name == "xterm":
1680
+ argv = [binary, "-u8", "-fa", "DejaVu Sans Mono", "-fs", "11",
1681
+ "-geometry", "110x32+50+50",
1682
  "-T", self.TERM_TITLE, "-e", "bash", "--login"]
1683
  else:
1684
  argv = [binary, "--title=" + self.TERM_TITLE, "-e", "bash --login"]
 
1710
  if not await self._start_vnc():
1711
  return False
1712
  await self._start_term()
1713
+ await asyncio.to_thread(self._suppress_session_popups)
1714
  self.started_at = time.time()
1715
  if self._healthy():
1716
  self.last_error = ""