分類
程序

在 CentOS 8 上使用 Xvfb 和 PyAutoGUI

本文介紹在 CentOS 8 上使用 PyAutoGUI 操作運行與 Xvfb 桌面環境中的 Firefox 所需的準備。由於所操作網頁需要登錄並有 OTP,所以還需要使用 VNC 來手動輸入密碼以做準備工作。

安裝 Xvfb

sudo yum install xorg-x11-server-Xvfb
#啓動 Xvfb
Xvfb :0 -screen 0 1366x768x24+32 -br +bs -ac &
#修改環境變量 DISPLAY
export DISPLAY=:0
#查看環境變量 DISPLAY
$DISPLAY
#查看 Xvfb 進程
ps -ef | grep Xvfb

如果只是爲了使用 webdriver 操作瀏覽器那麼這樣安裝運行 Xvfb 後就可以了,但是我們要使用 PyAutoGUI,所以還有依賴要裝。

安裝火狐瀏覽器

我個人比較偏好 ESR 版火狐,下載後解壓就可以使用了。

tar -xf firefox-115.5.0esr.tar.bz2
cd Firefox
./firefox
#如果要指定窗口大小可以
./firefox -width 1350 -height 764

安裝 x11vnc 服務

其實只要下載執行檔,運行即可,非常簡單。不過 x11vnc 12 年未有更新,不知道還能用多久。如果那天不能用了可以嘗試 Tiger VNC。

mv x11vnc-0.9.13_amd64-Linux x11vnc
chmod +x x11vnc
#運行 vnc server,密碼設置長一點,端口是 9999
./x11vnc -display :0 -ncache 0 -passwd piHrcHxmJauvIOftenUseA64digitPasswordpokiHJHQWdsgcGFTG -rfbport 9999
#上面命令在一次連接後會停止,如果要服務一直可以用,就加上 forever 參數
./x11vnc -display :0 -ncache 0 -passwd piHrcHxmJauvIOftenUseA64digitPasswordpokiHJHQWdsgcGFTG -rfbport 9999 -shared -forever
#注意服務器的網絡防火牆要打開 9999 端口
#用 nmap 查看端口是否打開
nmap -p 9999 1.1.1.1

Fedora 本地可以安裝 Remmina 作爲 VNC 客戶端。

sudo dnf install remmina -y
#如果想要使用 socks5 代理
proxychains4 /usr/bin/remmina

打開 Remmina 後在地址欄的協議選項裏選擇 VNC,然後地址填 1.1.1.1:9999 回車就可以連上服務器的桌面並看到剛剛打開的火狐瀏覽器進行設置了。點左上角的 + 號可以添加 profile,這樣下次雙擊就能連上 VNC 了。

安裝與配置 PyAutoGUI

我自己從源碼編譯的 Python 一直提示沒有 _tkinter 模塊。搜了半天沒有解決,於是使用系統自帶的 Python 3.9 得以解決。雖然我是用 Python 3.11 開發的,但是 Python 3.9 跑起來也沒問題。

import _tkinter # If this fails your Python may not be configured for Tk
ImportError: No module named _tkinter
#安裝 Python 3.9 以及依賴
sudo yum install libnsl ImageMagick xclip
sudo yum install python39 python39-tkinter

#xdotool 並不支持 Xvfb,所以不用裝
#sudo yum install xdotool

#創建虛擬環境
cd your_project
python3.9 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

示例代碼

import json
import random
import sys
import requests
import time
import logging
import os
import pyperclip
import subprocess
from urllib.parse import urlparse, parse_qs, urlunparse
from dotenv import load_dotenv
import psutil
import pyautogui
import pyscreeze

script_dir = os.path.dirname(os.path.realpath(__file__))

load_dotenv()
api_key = os.getenv("API_KEY")
proxy = os.getenv("PROXY")
de = os.getenv("DE")
batch = int(os.getenv("BATCH"))

if proxy is None:
    proxies = None
else:
    proxies = {"http": proxy, "https": proxy}

logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger()
# Create a file handler to save logs to a file
log_file = os.path.join(script_dir, "logfile.log")
file_handler = logging.FileHandler(log_file)

# Set the logging level for the file handler (if different from the root logger)
file_handler.setLevel(logging.INFO)  # Adjust the log level if needed

# Create a formatter and add it to the file handler
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
file_handler.setFormatter(formatter)

# Add the file handler to the logger
logger.addHandler(file_handler)


def activate_window(window_title):
    if de == "Xvfb":
        firefox_exists = False
        for proc in psutil.process_iter():
            try:
                if "firefox" in proc.name().lower():
                    firefox_exists = True
                    break
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass
        if firefox_exists is False:
            subprocess.Popen(
                [
                    "/home/centos/fred/programs/firefox/firefox",
                    "-width",
                    "1350",
                    "-height",
                    "764",
                ]
            )
            logger.info("firefox started")
            time.sleep(10)
    elif de == "Xfce":
        command = f"xdotool search --onlyvisible --name '{window_title}' windowactivate"
        subprocess.run(command, shell=True)


def wait_for_image(image_path, timeout=10):
    start_time = time.time()
    while time.time() - start_time < timeout:
        try:
            location = pyautogui.locateOnScreen(
                image_path, region=(0, 0, 1360, 760), confidence=0.9, grayscale=True
            )
            if location:
                return location
        except pyautogui.ImageNotFoundException:
            pass
        time.sleep(1.5)
    return None


def wait_for_images(image_path, timeout=10):
    start_time = time.time()
    while time.time() - start_time < timeout:
        try:
            location = pyautogui.locateAllOnScreen(
                image_path, region=(0, 0, 1366, 760), confidence=0.9
            )
            if location:
                return list(location)
        except pyautogui.ImageNotFoundException:
            pass
        except pyscreeze.ImageNotFoundException:
            pass
        time.sleep(1.5)
    return []

def right_click():
    pyautogui.mouseDown(button="right")  # Perform a right-click
    time.sleep(0.1)  # Adjust the delay if needed (time in seconds)
    pyautogui.mouseUp(button="right")  # Release the right-click


def triple_click(x, y):
    for _ in range(3):
        pyautogui.click(x, y)
        time.sleep(0.1)

def get_data(obj):
    start_time = time.time()
    time.sleep(0.5)
    activate_window("Mozilla Firefox")
    time.sleep(0.5)
    # load webpage
    url_profile = obj["contact_name_href"]
    if url_profile.find("?") != -1:
        url_profile = url_profile[: url_profile.find("?")]
    logger.info(url_profile)
    # open a new tab
    # pyautogui.hotkey('ctrl', 't')
    pyautogui.hotkey("ctrl", "l")
    time.sleep(0.5)
    pyautogui.typewrite(url_profile)
    time.sleep(0.5)
    pyautogui.press("enter")
    time.sleep(8)

    # check page loaded
    image_path = os.path.join(script_dir, "img/ContactDetails.png")
    loaded = wait_for_image(image_path, 40)

    # Box(left=535, top=541, width=74, height=19)
    if loaded:
        logger.info("Page loaded")

    # LinkedIn
    image_path = os.path.join(script_dir, "img/LinkedIn.png")
    l = wait_for_images(image_path, 3)
    l_index = 0
    retry = 0
    temp_l = None
    while l_index < len(l):
        logger.info(f"l_index:{l_index+1}/{len(l)}")
        if temp_l is not None:
            if temp_l[0] == l[l_index][0]:
                l_index = l_index + 1
                continue
        li = l[l_index]
        pyautogui.moveTo(li, duration=2, tween=pyautogui.easeInOutQuad)
        time.sleep(0.5)
        pyautogui.click(li)
        time.sleep(2)
        pyautogui.hotkey("ctrl", "l")
        time.sleep(0.5)
        pyautogui.hotkey("ctrl", "c")
        time.sleep(0.5)
        pyautogui.hotkey("ctrl", "w")
        time.sleep(0.5)
        copied_text = pyperclip.paste()
        url = copied_text.strip()
        url = get_link_from_redirect(url)

        if url is not None and url != "":
            # logger.info(len(url))
            if url.find("linkedin") == -1:
                logger.info("not found 'linkedin'")
                if retry < 3:
                    retry = retry + 1
                else:
                    l_index = l_index + 1
                continue

            # personal LindedIn
            if li[0] < loaded_x_left:
                obj["LinkedIn_Personal_URL"] = url
            else:
                obj["LinkedIn_URL"] = url
        temp_l = li
        l_index = l_index + 1

    # Supplemental_Email
    image_path = os.path.join(script_dir, "img/Supplemental.png")
    l = wait_for_image(image_path, 3)
    if l:
        pyautogui.moveTo(
            l[0] + l[2] + 50 + random.randint(-5, 5),
            l[1] + l[3] / 2,
            duration=1,
            tween=pyautogui.easeInOutQuad,
        )
        time.sleep(1)
        right_click()
        time.sleep(1)
        pyautogui.hotkey("l")
        time.sleep(1)
        pyautogui.hotkey("esc")
        # [email protected]
        copied_text = pyperclip.paste()
        obj["Supplemental_Email"] = copied_text.strip()

    # Local address
    image_path = os.path.join(script_dir, "img/Local.png")
    l = wait_for_image(image_path, 3)
    if l:
        x = l[0] + l[2] + 30 + random.randint(-5, 5)
        pyautogui.moveTo(x, l[1] + l[3] / 2, duration=1, tween=pyautogui.easeInOutQuad)
        time.sleep(1)
        triple_click(x, l[1] + l[3] / 2)
        time.sleep(1)
        pyautogui.hotkey("ctrl", "c")
        time.sleep(1)
        # [email protected]
        copied_text = pyperclip.paste()
        obj["Local_Location_Address"] = copied_text.strip()

def main(max_id):
    failed_list = []
    for i in range(batch):
        logger.info(f"batch:{i+1}/{batch}")
        obj = get_job()
        if obj is None:
            continue
        if obj["contact_name_href"] == "" or obj["contact_name_href"] is None:
            res = post_job(obj)
            logger.info(res)
            continue

        if obj["id"] > max_id:
            logger.info("max_id reached")
            continue
        obj = get_data(obj)
        if obj["message"] != "success":
            if obj["id"] in failed_list:
                res = post_job(obj)
                logger.info(res)
            else:
                failed_list.append(obj["id"])
            continue

        res = post_job(obj)
        logger.info(res)

if __name__ == "__main__":
    # time.sleep(10)
    # countdown
    for i in range(6):
        logger.info(f"countdown:{6-i}")
        time.sleep(1)

    # get max id from command
    if len(sys.argv) > 1:
        max_id = int(sys.argv[1])
        logger.info(f"max_id:{max_id}")
    else:
        max_id = 9999999

    main(max_id)
分類
Linux

Fedora 35 失去支持後升級 37

Fedora 失去支持後

失去支持後,dnf upgrade 會報錯 "Failed to download metadata for repo 'updates'" 。可以修改 /etc/yum.repos.d/ 中如下四個文件:fedora.repo fedora-modular.repo fedora-updates.repo fedora-updates-modular.repo 中的兩行

baseurl=https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/$releasever/Everything/$basearch/
#metalink=https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch

修改後便不再報錯,但是由於 35 已失去官方支持,所以不會再有更新。

升級 Fedora 系統

!畢竟是更新系統,所以重要資料記得備份。!

可以通過 dnf system-upgrade 來方便的升級到 36 或 37(但是不能直接升級到38)。升級系統請參考官方的 DNF System Upgrade 以及 Upgrade to Fedora 37 from Fedora 36 using DNF。大約要下載 2G 大小的文件,下載後升級過程需要半個小時左右。主要命令如下:

#更新一下,如果有更新之後要重啓一下
sudo dnf upgrade --refresh
#安裝系統升級 dnf 插件
sudo dnf install dnf-plugin-system-upgrade
#下載要升級到的版本,如 37
sudo dnf system-upgrade download --releasever=37
#下載完畢,執行系統更新
sudo dnf system-upgrade reboot

執行 system-upgrade download 前需要把前面四個文件改回去,不然 archive 站點是沒有新系統的資料包的。

分類
Linux 软件

Fedora 35 與 Nvidia GPU 驅動

TL;NR

如果電腦開啓了 Secure Boot, 又不想頭痛地處理簽名,可以關掉。然後跟隨這個網頁的方法安裝開源的 Nvidia 驅動: Howto/NVIDIA。或者跟隨這個網頁安裝 Nvidia 官方的驅動:Fedora 36/35/34 NVIDIA [515.57 / 510.73.05 / 470.129.06 / 390.151 / 340.108] Drivers Install Guide。這個網頁裏也有介紹如果禁用 Fedora 自帶的 Nouveau 驅動的方法。

The Story

打算嘗試在 Fedora 上編輯視頻,一番搜索後發現 DaVinci Resolve 好像很強大,而且還有 Linux 的免費版本。下載安裝很順利,但是打開後歡迎頁面是黑屏。禁用 Secure Boot 裝了 rpmfusion 推薦的驅動後可以打開了,但是 GPU 設置成 CUDA 模式提示無法渲染圖像,錯誤編碼 999,改成 OpenGL 模式不報錯,但是連 JPG 圖像的預覽都是花的,我以爲是 rpmfusion 的驅動不行(實際不是)。於是去裝官網驅動,禁用了 Nouveau 驅動後安裝成功,但是 DaVinci 還是無法使用,後來發現可能是筆記本自動選擇顯卡 Optimus 有關,可以參考 OptimusHow to Set Nvidia as Primary GPU on Optimus-based Laptops。我並沒有把 Nvidia 設置爲默認,因爲覺得平常板載就夠了。所以後來我使用環境變量的方法成功運行了 DaVinci Resolve

__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia /opt/resolve/bin/resolve

最後我發現相機拍攝的 mov 視頻文件導入後還是只有音頻,想要編輯的話要先對視頻進行轉碼。而且導出格式也有蠻多限制,所以就放棄了 DaVinci Resolve。

然後我搜索到 Linux 平臺另一款「強大」的視頻編輯器 Lightworks,到官網下載免費版體驗,發現需要註冊,註冊時發現有 recaptcha 人機驗證,我換了好幾個網絡居然都無法通過。無奈從網上找了個安裝包,安裝後打開軟件發現需要登錄才能使用所以還是要註冊。最後是第二天在手機瀏覽器裏註冊成功了。然後發現導出 1080p 的視頻居然是付費版本才有的功能,2022年了喂~

最後我去看 Fedora 的手冊,上面推薦 Kdenlive,從官網直接下載 AppImage 檔直接運行,視頻和圖片都順利導入,導出也都沒有什麼限制,h264、h265、ProRes 全都 OK!而且也支持視頻穩定和關鍵幀調整。雖然兩個視頻漸變過度的 Mixes 操作很怪異,但是至少能達到想要的效果。時間軸的操作可能由於還不會用,所有也感覺不太順手,但是至少可以正常導入、剪輯、調整顏色、加字幕和出片了。

分類
Linux

Fedora 35 安裝 VirtualBox

沒想到給 Fedora 35 安裝 VirtualBox 會遇到這麼一個坑,所以記錄下。如果你的電腦沒有啓用 EFI Secure Boot 應該不會遇到這個問題。報錯信息如下:

vboxdrv.sh: failed: modprobe vboxdrv failed. Please use 'dmesg' to find out why.

There were problems setting up VirtualBox.  To re-start the set-up process, run
  /sbin/vboxconfig
as root.  If your system is using EFI Secure Boot you may need to sign the
kernel modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) before you can load
them. Please see your Linux system's documentation for more information.

如果你不想關閉安全啓動,那麼可以按如下步驟來解決:

1, 安裝 mokutil

sudo dnf update
sudo dnf install mokutil

2, 在新文件夾裏創建 RSA 密鑰

sudo -i
mkdir /root/signed-modules
cd /root/signed-modules
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=VirtualBox/"
chmod 600 MOK.priv

3, 準備導入密鑰的密碼,等下重啓電腦後會詢問你設置的密碼。

sudo mokutil --import MOK.der

4, 重啓電腦,電腦會進入一個藍屏,選擇 Enroll MOK --> Continue --> 輸入你剛剛設置的密碼,然後你的電腦會重啓。

5, 進入剛剛的文件夾新建一個腳本。

cd /root/signed-modules
nano sign-virtual-box

腳本內容如下:

#!/bin/bash

for modfile in $(dirname $(modinfo -n vboxdrv))/*.ko; do
  echo "Signing $modfile"
  /usr/src/kernels/$(uname -r)/scripts/sign-file sha256 \
                                /root/signed-modules/MOK.priv \
                                /root/signed-modules/MOK.der "$modfile"
done

如果腳本執行失敗了,可以嘗試運行下面命令,然後根據結果修改上面腳本。

find /usr/src -name signfile

5, 爲腳本增加執行權限並運行。

chmod 700 sign-virtual-box
./sign-virtual-box 

6, 把簽名後的驅動加入內核中就可以了。

modprobe vboxdrv

Ubuntu 用戶可以參考這篇 https://stegard.net/2016/10/virtualbox-secure-boot-ubuntu-fail/。以上解決辦法由 Younes LAB 作答與 Sign virtual box modules (vboxdrv, vboxnetflt, vboxnetadp, vboxpci) Centos 8 - Stack Overflow


從 VirtualBox RPM 源安裝 VirtualBox

由於之前沒有搜到上面的辦法,還以爲是安裝的問題,嘗試了從 VirtualBox RPM 源安裝 VirtualBox,其實是不能解決問題的,但是這裏也記錄一下。

1, 安裝依賴。

sudo dnf -y install @development-tools
sudo dnf -y install kernel-headers kernel-devel dkms elfutils-libelf-devel qt5-qtx11extras

2, 添加VirtualBox RPM 源。

Fedora 36 / Fedora 35:

cat <<EOF | sudo tee /etc/yum.repos.d/virtualbox.repo 
[virtualbox]
name=Fedora $releasever - $basearch - VirtualBox
baseurl=http://download.virtualbox.org/virtualbox/rpm/fedora/35/\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://www.virtualbox.org/download/oracle_vbox.asc
EOF

Fedora 34:

cat <<EOF | sudo tee /etc/yum.repos.d/virtualbox.repo 
[virtualbox]
name=Fedora $releasever - $basearch - VirtualBox
baseurl=http://download.virtualbox.org/virtualbox/rpm/fedora/34/\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://www.virtualbox.org/download/oracle_vbox.asc
EOF

Fedora 33:

cat <<EOF | sudo tee /etc/yum.repos.d/virtualbox.repo 
[virtualbox]
name=Fedora $releasever - $basearch - VirtualBox
baseurl=http://download.virtualbox.org/virtualbox/rpm/fedora/33/\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://www.virtualbox.org/download/oracle_vbox.asc
EOF

3, 導入 VirtualBox GPG 密鑰,確認指紋匹配後按 y。

sudo dnf search virtualbox
Fedora  -  - VirtualBox                                 58  B/s | 181  B     00:03
Fedora  -  - VirtualBox                                906  B/s | 1.7 kB     00:01
Importing GPG key 0x98AB5139:
 Userid     : "Oracle Corporation (VirtualBox archive signing key) <[email protected]>"
 Fingerprint: 7B0F AB3A 13B9 0743 5925 D9C9 5442 2A4B 98AB 5139
 From       : https://www.virtualbox.org/download/oracle_vbox.asc
Is this ok [y/N]: y

4, 安裝 VirtualBox。

sudo dnf install VirtualBox-6.1

5, 把當前用戶添加到 vboxusers 用戶組。

sudo usermod -a -G vboxusers $USER
newgrp vboxusers

然後就可以通過命令 virtualbox 或應用菜單 》System 》Oracle VM VirtualBox來啓動了。但是這個時候還沒有裝 Extension Pack,表現爲虛擬機只支持 USB 1.1,屏幕無法縮放。好在擴展包直接從官網下載就可以,然後直接雙擊就能順利運行安裝。

此安裝教程來自 How To Install VirtualBox 6 on Fedora 36/35/34/33/32 - ComputingForGeeks

分類
Linux

Install Fedora 35 on Dell Inspiron 1525

The Inspiron 1525 is Emanon's first (and only) laptop, which brought almost 13 years ago. When it got laggy and hard to run Adobe software, we brought an Acer desktop. Several years later, we got some video tasks to do, so we gave the Acer desktop to Emanon's sister, who didn't have a desktop. From that on, we started using a Dell desktop in daily life. But we only got one PC, we had to take turns recently. I found the old desktop after a room tidy up and thought maybe it can still run for easy tasks in daily life.

My Inspiron 1525 has a 2 GB Memory, a 2-core CPU, a 120 GB hard disk and a 15.4" screen(which is much bigger than my phone). Fortunately, it meets the minimum hardware of Fedora 35. I use Xfce desktop environment for many years, it's fast and has almost everything I need. So I download Fedora 35 Xfce Desktop and burn it into my old 2 GB flash disk with the official tool Fedora Media Writer.

sudo dnf install mediawriter
mediawriter

Then insert the flash disk into 1525, press power button. When you see the progress bar go to the end, keep hitting F12 then select USB Storage Device. You'll boot into Fedora 35 Xfce in a moment. If you haven't back up your files, you could do it now. If you don't have a wired Internet connection, you should download and copy the two files below for fixing the Wi-Fi later. Run the Install to Hard Drive in the desktop to install Fedora OS. For more details, please refer to Installing Using Anaconda. After that, reboot your laptop and remove the flash disk.

You'll see the Wi-Fi is failed, even after you updated all the software. The good news is there are ways to fix. Download broadcom-wl-6.30.163.46 (backup link), extract it. Run the following commands to get the working driver and copy them to your system.

#sudo yum install b43-fwcutter
sudo b43-fwcutter -w /lib/firmware broadcom-wl-6.30.163.46/broadcom-wl-6.30.163.46.wl_apsta.o
sudo sync
sudo /sbin/modprobe -r b43
sudo /sbin/modprobe b43

Now you can browse the web or do some text work on it. If you want some multimedia pleasure, you might need VLC. And before you install VLC, you need to enable RPM Fusion first.

sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm

本文更新於 2022/03/21。

分類
Linux

Fedora 31 L2TP PSK 連接失敗

有個預共享密鑰的 L2TP VPN,在安卓和 Windows上,不做額外設置的情況下都能連接上。但是 Fedora 31 上卻不行,試着修改下加密選項,也不成功。後來搜索到說是因為自帶的 libreswan 不在支持弱加密導致的。

解決方法

刪除已有的 VPN 配置
dnf remove libreswan
dnf remove strongswan
dnf install strongswan
新建 VPN 配置

錯誤現象

Started the VPN service, PID 17688
Saw the service appear; activating connection
VPN connection: (ConnectInteractive) reply received
VPN plugin: state changed: stopped (6)
VPN service disappeared
VPN connection: failed to connect: 'Remote peer disconnected'

原因

IKE DH algorithm ‘modp1024’ is not supported in libreswan with 5.5.7-200 kernel in FC31.

其他有用信息

#將網絡日誌調至調試級別(更多)
nmcli general logging level DEBUG
#將網絡日誌調至信息級別(默認)
nmcli general logging level INFO
#查看網絡連接日誌
journalctl -u NetworkManager
#服務的啟動與停止
systemctl stop strongswan.service
systemctl stop xl2tpd.service
#查看本機的網絡連接
nmcli con show
#啟動指定 UUID 的網絡連接
nmcli con up uuid 40c58e49-5b99-4432-85ae-a6dc9c1c37a3
#把指定 UUID 網絡連接的日誌保存到 t.txt
journalctl -xe NM_CONNECTION=40c58e49-5b99-4432-85ae-a6dc9c1c37a3 + NM_DEVICE=enp0s3 > t.txt

成功連接的版本信息

strongswan-5.8.2-3.fc31.x86_64
Linux 5.8.17-100.fc31.x86_64 #1 SMP Thu Oct 29 18:58:48 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

參考資料:Cannot Connect to VPN 感謝 nrv 和 insomniacjunkie 的回復。

分類
软件

Linux 使用 Python 操作剪切板

還是那個簡繁轉換的需求, zhconv 似乎不能直接給它傳一段文字來轉換,只能轉換文件或者在 Python 中調用。

Fedora

先安裝 xclip 依賴,再安裝 pyperclip:

sudo dnf install xclip
sudo pip3 install pyperclip

然後新建一個 Python 腳本 /home/[YOURNAME]/scripts/s2t.py:

import pyperclip
from zhconv import convert

clipString = pyperclip.paste()
clipStringTC = convert(clipString, 'zh-hant')
pyperclip.copy(clipStringTC)

最後為了方便使用,給腳本設置一個別名

alias t='python3 /home/[YOURNAME]/scripts/s2t.py'

但是如果想讓別名保存下來,以後每次都能用,Fedora 需要把別名加到家目錄的 .bashrc 文件裏:

nano ~/.bashrc
alias t='python3 /home/[YOURNAME]/scripts/s2t.py'

Termux

Termux 無法使用 pyperclip 來操作剪切板,但是可以通過 Termux API 來操作。對應的 Python 這樣:

import subprocess
from zhconv import convert

clipString = subprocess.getoutput("termux-clipboard-get")
clipStringTC = convert(clipString, 'zh-hant')
subprocess.getoutput("termux-clipboard-set \'"+clipStringTC+"\'")

本文更新於 2022/07/29。