我撰寫了一個使用keyboardlib 的小型 python 程式(screen.py)。程式的本質是按 ctrl 1 截屏,然后按 ctrl 2 將它們發送到我的 github 存盤庫。使用鍵盤庫需要程式必須通過 sudo 啟動。
螢屏.py:
import keyboard
import pyautogui
import os
screenshot_num = 0
PICS_DIR = os.path.join(os.getcwd(), "pics")
SEND_TO_GIT_SCRIPT = os.path.join(os.getcwd(), "send.sh")
os.makedirs(PICS_DIR, exist_ok=True)
def make_screenshot():
global screenshot_num
myScreenshot = pyautogui.screenshot()
myScreenshot.save(os.path.join(PICS_DIR, str(screenshot_num) '.png'))
screenshot_num = 1
def send_to_git():
os.system(SEND_TO_GIT_SCRIPT)
keyboard.add_hotkey('Ctrl 1', make_screenshot)
keyboard.add_hotkey('Ctrl 2', send_to_git)
keyboard.wait('Alt q')
問題是當程式執行到呼叫send.sh(下面的代碼)時,我收到以下錯誤:
錯誤:
? sudo python3 screen.py
New Pics
3 files changed, 0 insertions( ), 0 deletions(-)
rewrite screen/pics/0.png (97%)
rewrite screen/pics/1.png (97%)
rewrite screen/pics/2.png (97%)
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
發送.sh:
git add ./pics/*
git commit -m 'New Pics'
git push
我通過 ssh 連接到 github,密鑰是通過 sudo ssh-keygen 創建的。我通過 ssh 連接到 github。我添加了使用和不使用 sudo 生成的密鑰。
uj5u.com熱心網友回復:
您需要以git普通用戶身份運行這些命令。
不幸的是,Python 只允許你放棄當前行程的權限;如果您仍然需要運行一些特權代碼,您就不能再切換回來。
最佳實踐和通常只是良好的安全衛生將是洗掉所有不需要它們的 root 特權。我試圖重構您的代碼以盡可能少地運行root,但在這種情況下這很困難。必須將部分分割成子流程,這在這里沒有多大意義。
這是一個快速而骯臟的重構,它以呼叫用戶的身份運行 shell 子行程,并修復任何創建的檔案的所有權,以避免最終出現root由普通用戶創建的 -owned 檔案,這些檔案可能在他們的主目錄或它們應該在的其他地方檔案的控制。
import os
import subprocess
import keyboard
import pyautogui
screenshot_num = 0
# no need for os.getcwd() here
# see https://stackoverflow.com/questions/45591428
PICS_DIR = "pics"
SEND_TO_GIT_SCRIPT = os.path.join(".", "send.sh")
def fix_owner(filename: str) -> None:
"""
Ensure that the file is owned by the unprivileged invoking user
"""
os.chown(filename, int(os.environ["SUDO_UID"]), int(os.environ["SUDO_GID"]))
def unprivileged_subprocess(command: str) -> CompletedProcess:
"""
Run the shell commands as the unprivileged invoking user
"""
return subprocess.run(
["su", "-", os.environ["SUDO_USER"], "-c", command],
check=True)
os.makedirs(PICS_DIR, exist_ok=True)
fix_owner(PICS_DIR)
def make_screenshot():
global screenshot_num
filename = os.path.join(PICS_DIR, str(screenshot_num) '.png')
myScreenshot = pyautogui.screenshot(filename)
fix_owner(filename)
screenshot_num = 1
def send_to_git():
unprivileged_subprocess(SEND_TO_GIT_SCRIPT)
keyboard.add_hotkey('Ctrl 1', make_screenshot)
keyboard.add_hotkey('Ctrl 2', send_to_git)
keyboard.wait('Alt q')
如果未填充預期的環境變數等,這將崩潰并顯示無用的錯誤訊息;如果腳本沒有使用sudo.
也許更好的通用設計是將特權代碼作為持久子行程(subprocess.Popen)運行,并在啟動后立即洗掉主腳本的特權。不幸的是,我對 PyAutoGUI 的了解還不夠,keyboard無法嘗試在這種情況下實作它。模糊地說,有什么東西打開鍵盤設備root,然后以某種方式將結果傳達給呼叫者?或者,也許僅open將設備置于特權模式就足夠了,然后放棄所有后續處理的特權。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/480927.html
