Skip to content

Home

Journal-2025

11.4

小米双开ChatGPT App问题

双开的ChatGPT应用会报错Somthing went wrong: Check that Google Play is enabled on your device...,这是因为ChatGPT对于Play商店完整性的检验较为严格,仅仅有Google框架而没有Play商店无法通过检查。系统在双开时会自动将Google框架服务也安装到双开空间,但Play商店则不会。因此,通过adb手动双开Play商店即可:

adb shell cmd package install-existing --user 999 com.android.vending # 双开空间的user id一般为999

检查Google三件套是否存在:

# 主空间
adb shell cmd package list packages --user 0   com.google.android.gms
adb shell cmd package list packages --user 0   com.android.vending
adb shell cmd package list packages --user 0   com.google.android.gsf
# 双开空间
adb shell cmd package list packages --user 999 com.google.android.gms
adb shell cmd package list packages --user 999 com.android.vending
adb shell cmd package list packages --user 999 com.google.android.gsf

11.3

journalctl持续监控

sudo journalctl -u xxxx.service -f

11.2

curl指定网卡

curl --interface wg0 example.com

11.1

添加Google AI Mode为自定义搜索引擎

url:https://www.google.com/search?udm=50&q=%s

10.30

自定义vLLM进程名前缀

新版的vLLM设置了更简洁的进程名形如VLLM::EngineCore_DP0,并且支持通过环境变量自定义,可以用来在进程名上展示信息。

export VLLM_PROCESS_NAME_PREFIX="非紧急任务_用卡联系_VLLM"

10.22

Ubuntu 24.04无法安装speedtest-cli

官网的说明使用了添加源的方法,但目前packagecloud上的源没有提供24.04 noble版本,导致出现E: The repository 'https://packagecloud.io/ookla/speedtest-cli/ubuntu noble Release' does not have a Release file.报错。

可以直接使用22.04 jammy的包:

sudo sed -i 's/noble/jammy/g' /etc/apt/sources.list.d/ookla_speedtest-cli.list

sudo apt update
sudo apt install speedtest

Ubuntu常见发行版代号

发行版 代号
Ubuntu 26.04 Resolute Raccoon
Ubuntu 24.04 Noble Numbat
Ubuntu 22.04 Jammy Jellyfish
Ubuntu 20.04 Focal Fossa
Ubuntu 18.04 Bionic Beaver

10.21

用户态oom-killer

如果有某个程序出问题,短时间内分配并占用大量内存,内核中的oom-killer往往要一段时间之后才行动,此时图形界面往往已经持续卡顿了,体验较差。使用用户态oom daemon可以更早发现问题,以及通过直接杀死整个cgroup来避免问题进程反复重启。

sudo systemctl enable --now systemd-oomd.service
stress --vm 2 --vm-bytes 30G --timeout 30s # 进行内存压力测试

10.20

curl跟随301、302重定向

curl -L http://example.com

10.19

WireGuard组网基础上远程控制安卓设备

blog

10.18

ssh隧道启用压缩

ssh -C ...

10.16

修复Google Play保护机制认证

Play保护机制认证缺失会导致Google Pay无法NFC支付、虚拟八达通无法导入手机等问题。Google官方给出了排查说明:查看和修正 Play 保护机制认证状态

值得注意的是:

  1. 有说法提到开发版系统(如小米的)可能会缺失认证;
  2. Play商店里面的“解决设备问题”按钮可能会提示“出现未知问题”,此时等几分钟再试可能问题会消失;
  3. Play Integrity API Checker应用可以检查具体的认证状态;

终端模拟器自带翻页&检索

使用Claude Code CLI时PgUp/PgDn按键不起作用了,此时使用Shift+PgUp/PgDn可以实现翻页,是一个更通用的快捷键(在Alacritty中有效,应该大多数终端模拟器都支持)。

Ctrl+Shift+F在当前窗口所有文本中检索(在Alacritty中有效)

10.8

文件完整性校验

b3sum,速度可达到md5sum的数十倍,且提供更强的安全性,比主打速度的xxh128sum还快1倍

10.6

i3lock半透明效果(旧方案)

之前使用X11+i3wm时,为了实现锁屏看板的效果,鼓捣了一个相对丑陋的方案:通过xprop将i3-lock窗口设为半透明,以便显示出锁屏下方的看板。

#!/bin/python3
import os
import subprocess

def exec(cmd) -> str:
    return subprocess.check_output(cmd, shell=True).decode("utf-8")

def check_locked() -> bool:
    try:
        exec("ps -e | grep -v i3lock-trans | grep i3lock")
    except Exception:
        return False
    return True

def set_opacity(window_id: int, opacity: float):
    # Disable compositor bypass
    exec(f"xprop -id {window_id} -f _NET_WM_BYPASS_COMPOSITOR 32c -set _NET_WM_BYPASS_COMPOSITOR 0")
    # Set opacity
    exec(f"xprop -id {window_id} -f _NET_WM_WINDOW_OPACITY 32c -set _NET_WM_WINDOW_OPACITY {int(opacity * 0xffffffff)}")

if __name__ == '__main__':
    if check_locked():
        print("Already locked")
        exit()
    os.system("i3lock -c 000000")
    wids = exec("xdotool search --class i3lock").strip().split("\n")
    wids = [int(w) for w in wids]
    for wid in wids:
        set_opacity(wid, 0.2)

Swaylock渲染终端看板作为锁屏

swaylock-plugin支持将其他窗口作为插件渲染到锁屏界面上,注意需要借助windowtolayer包将普通程序转换为使用wlr-layer-shell协议渲染:

swaylock-plugin --command-each "windowtolayer -- alacritty -e btm" # `btm` can be customized

便捷清理known_hosts

有时远程主机指纹发生变化,手动删除较为麻烦

ssh-keygen -R hostname

9.11

uv环境Python.h缺失问题

某些Python库需要使用Python头文件进行编译(如triton),可能会遭遇缺失Python.h头文件的问题,这是由于uv在当前环境所需Python版本在系统中已安装时会优先使用系统中的版本,而系统版本不一定安装了头文件包(如libpython3.12-dev

solution

uv python pin 3.12 --managed-python # 使用uv本地安装的python,自带头文件

9.10

ChatGPT会话记录导出

ChatGPT Exporter

8.26

Claude Code MCP

claude mcp add sequential-thinking -s user -- npx -y @modelcontextprotocol/server-sequential-thinking
claude mcp add -s user --transport http context7 https://mcp.context7.com/mcp --header "CONTEXT7_API_KEY: API_KEY"
claude mcp add playwright -s user -- npx -y @playwright/mcp
claude mcp add fetch -s user -- npx -y @kazuph/mcp-fetch

8.18

使用miniserve提供简单方便的高性能文件服务

cargo install miniserve
cd /path/to/serve
miniserve . --port <port>
curl localhost:port # check service

从已安装的Python包中重新打包whl包

有时遇到上游源挂了无法安装某个包,但本地已有一个环境此前安装过,可以从这个环境中重新打包whl文件。

cd .venv/lib/python3.12/site-packages
mkdir -p ~/temp/vllm_pack
cp -r vllm vllm-0.10.2.dev5+g08d5f7113.dist-info ~/temp/vllm_pack # 重新打包时要求这两个文件夹单独存在于一个目录下,因此我们将其复制到一临时文件夹下
cd ~/temp/vllm_pack
mkdir dist
wheel pack . dist # 将当前目录打包至dist文件夹
# 输出:Repacking wheel as dist/vllm-0.10.2.dev5+g08d5f7113-cp38-abi3-linux_x86_64.whl...OK

8.8

git bisect

用于二分查找debug,定位引入bug的第一个提交

git bisect start # 进入bisect模式
git bisect bad # 标记当前commit为bad
git bisect good v1.2.3 # 标记一个历史提交为good
# 此时提示:Bisecting: xxx revisions left to test after this (roughly xxx steps)
# 并自动跳转到bad和good中间的提交
# 对每一个跳转到的提交,通过测试确定bug是否存在,并进行标记:
git bisect good/bad
git bisect skip # 如果某个commit无法测试,可以跳过
# 最终,git bisect可以确定第一个bad commit
git bisect reset # 退出bisect模式并返回到bisect之前的位置

8.6

git小技巧

git diff --name-only # 只显示有差异的文件名
git push --force-with-lease # 防止覆盖他人新提交
git worktree add ../repo-fix bugfix/123 # 从当前仓库检出一个新的工作目录
git blame -w -L 10,80 app.py # -w忽略空白符噪音,-L指定行号范围
git restore --source=origin/main -- path/to/file # 从任意提交提取文件到工作区
git cherry-pick -n # -n 应用修改后不自动提交
git grep -n -p 'funcName' -I # 在仓库中做快速检索,-n开启行号,-p展示检索到的行所在的函数头,-I忽略二进制文件
git diff A..B / A...B # A..B表示范围(A, B],A...B表示B与A的对称差集
git show :/'fix login race' # 检索并展示最近的commit message里包含该字符串的提交
git tag --points-at HEAD # 列出指向某个提交的tag

7.31

浏览器快捷复制标题+url的分享文本

(已在Firefox测试)

新建书签,位置放到书签工具栏方便调用,内容为:

javascript:(function(){
  var title = document.title;
  if (title.length > 50) title = title.slice(0, 50) + '...';
  var text = title + '\n' + location.href;
  navigator.clipboard.writeText(text).then(function(){
    if (Notification.permission === 'granted') {
      new Notification('已复制分享链接', { body: text });
    } else {
      Notification.requestPermission().then(function(permission){
        if (permission === 'granted') {
          new Notification('已复制分享链接', { body: text });
        }
      });
    }
  });
})();

7.30

配置nvcc使用的gcc版本

使用FlashInfer时遭遇如下问题:

#error -- unsupported GNU version! gcc versions later than 13 are not supported! The nvcc flag '-allow-unsupported-compiler' can be used to override this version check; however, using an unsupported host compiler may cause compilation failure or incorrect run time execution. Use at your own risk.

网上帖子和文档都说使用NVCC_CCBIN='/usr/bin/gcc-12',但不知道为什么nvcc不认这个环境变量,始终还是使用gcc。最终使用NVCC_APPEND_FLAGS='-ccbin=gcc-12'解决。

7.22

无root从AUR安装软件包

没有root权限时,可以通过makepkg直接从PKGBUILD构建软件包,并进行本地安装。

(以p7zip为例)

git clone https://aur.archlinux.org/p7zip.git
cd p7zip

编辑PKGBUILD,将所有系统级路径替换为用户级路径:

/usr/bin -> "$HOME/.local/bin"
/usr/lib -> "$HOME/.local/lib"
/usr/share -> "$HOME/.local/share"
...

如果是$pkgdir/usr/bin等,也需要改为$pkgdir$HOME/.local/bin

makepkg # build

构建可能会出错,需要因地制宜解决路径和环境等问题。构建成功后得到类似p7zip-17.04-1-x86_64.pkg.tar.zst的文件。

检查.tar.zst包内容:

$ tar -I zstd -tf p7zip-17.04-1-x86_64.pkg.tar.zst
.BUILDINFO
.MTREE
.PKGINFO
home/user/
home/user/.local/
home/user/.local/bin/
home/user/.local/bin/7z
home/user/.local/bin/7za
home/user/.local/lib/
home/user/.local/lib/p7zip/
home/user/.local/lib/p7zip/7z
usr/
usr/share/
usr/share/licenses/
......

需确认主要包文件均正确放置在了~/.local下,并确认残留在/usr树下的文件无关紧要。

随后将tar.zst解包到home下:

tar -I zstd -xvf p7zip-17.04-1-x86_64.pkg.tar.zst \
    --strip-components=2 \ # strip the prefix `home/user`
    -C "$HOME" \ # destination
    "home/$(whoami)/.local" # match the ~/.local tree

配置相关环境变量(~/.zshrc):

export PATH="$HOME/.local/bin:$PATH"
export MANPATH="$HOME/.local/share/man:$MANPATH"

验证:

7z --help

6.9

git查询各分支设定的remote

git branch -vv

6.9

Polybar进阶配置

文件系统模块自定义别名

原配置不支持设置别名,如果挂载的路径过长会比较难看,可以通过继承的方式分子模块自定义:

[fs-base]
type = internal/fs
interval = 25

label-mounted = %{F#F0C674}%mountpoint%%{F-} %percentage_used%%

label-unmounted = %mountpoint% not mounted
label-unmounted-foreground = ${colors.disabled}

[module/fs-root]
inherit = fs-base
mount-0 = /
; replace %mountpoint% here with customized tag
label-mounted = %{F#F0C674}/%{F-} %percentage_used%%

[module/fs-data]
inherit = fs-base
mount-0 = /home/terrasse/DATA
label-mounted = %{F#F0C674}D%{F-} %percentage_used%%

网络模块显示网速

[module/wlan]
inherit = network-base
interface-type = wireless
label-connected = %{F#F0C674}%ifname%%{F-} %essid% %local_ip% %{T3}↑%{T-}%upspeed% %{T3}↓%{T-}%downspeed%

这里为了更美观,使用了不同的字体显示↑↓,语法为%{T3}切换预先定义的第3个字体,%{T-}重置默认字体。

注意,定义字体时下标从0开始,但引用时下标从1开始

; font-N = <fontconfig pattern>;<vertical offset>
font-0 = monospace;2
font-1 = monospace:size=20;5
font-2 = "Noto Sans:size=20;5"

穷举破解压缩包密码

使用Jhon the Ripper

rar2john xxx.rar > hast.txt # extract hash
john --format=RAR5-opencl \ # use GPU, or CPU: --format=RAR5
     --mask='?1?1?1?1?1?1?1?1?1?1?1?1?1' \ # use mask specify passphrase format
     --min-len=1 --max-len=13 \
     --1='?l?d.' \ # consists of lower case letters and numbers and '.' ([a-z0-9\.])
     hash.txt # target hash file

6.8

YAML高级语法

---
# Base config with anchors, tags, nested anchor & custom include
base: &base
  db: !!str mysql             # tag as string
  port: !!int "3306"          # tag as integer
  debug: !!bool "false"       # tag as boolean
  logging: &logconf           # nested anchor for logging
    level: !!str INFO
    to_file: !!bool "false"
  common_settings: !include "common.yaml"  # custom include tag

---
# Dev config: merge base, override fields, use sequence tag
dev: &dev
  <<: *base                   # merge entire base
  db: postgres                # override default db
  logging:
    <<: *logconf              # merge nested logging
    to_file: !!bool "true"    # override only this field
  feature_flags: !!seq        # tag as sequence
    - featureA
    - featureB

---
# Prod config: multi-merge, override, custom encrypted tag, map tag
prod:
  <<: [*base, *dev]           # merge base then dev (dev overrides base)
  port: 5432                  # override port again
  encrypted_key: !Encrypted "c2VjcmV0X2tleQ=="  # custom encrypted tag
  extra: !!map                # tag as map
    region: us-west
    replicas: !!int "8"

6.7

Selenium自动更新driver

使用chromedriver_autoinstaller

chromedriver_autoinstaller.install()

PyInstaller将Python项目打包为exe

pyinstaller -F <entry.py> -n <output_exe_name> --add-data "<source_path>:<target_path>" -i <icon_path>

6.1

安卓安装旧版本应用

现在已经没几个靠谱的平台提供旧版本安装包了

5.25

Zotero界面缩放

打开高级配置编辑器,修改layout.css.devPixelsPerPx属性值

Jupyter Notebook设置环境变量

有时需要在Notebook中指定环境变量(如CUDA_VISIBLE_DEVICES)可以使用魔法命令:

%env CUDA_VISIBLE_DEVICES=2,3

(需要在import torch之前执行)

5.20

VS Code keyring问题

solution

有时VS Code无法正确识别当前系统使用的keyring管理器(或未安装,推荐安装gnome-keyring),可以先尝试手动指定管理器,确认可用后添加到~/.vscode/argv.json中持久化。

code --verbose --vmodule="*/components/os_crypt/*=1" --password-store="gnome-libsecret" | grep OSCrypt

如果出现类似Selected backend for OSCrypt: GNOME_LIBSECRET,则说明正常工作了。

~/.vscode/argv.json

{
    // ...
    "password-store": "gnome-libsecret"
}

5.17

无权限时更换默认shell

之前写“共用同一个Linux user时简单隔离”时提到可以使用RemoteCommand /home/user/user1/init.sh实现自定义shell,但这种写法会导致ssh host echo 1这样的自定义命令无法运行。因此可以改为在~/.bash_profile(此配置仅在登录shell被打开时执行,是最佳选择)中进行shell切换,通过条件可限制为仅在交互式shell中执行。

~/.bash_profile末尾添加:

if [[ $- == *i* ]] && [ -t 1 ]; then
  export SHELL=$HOME/.local/bin/zsh
  exec $SHELL -l
fi

链式ssh技巧

有时需要ssh登录host1后紧接着登录host2(区别于使用ProxyJump,此处的ssh host2需要在host1上执行,因为私钥在host1上而不在本地)

可用-t参数强制启用伪终端:

ssh host1 -t ssh host2

进一步地,可以一步到位调用host2上的交互式程序,从而减少程序退出后暴露远程shell的安全风险:

ssh host1 -t ssh host2 -t nvitop

但上述命令可能由于nvitop不在系统级PATH中而失败,此时需要使用bash -l来加载~/.bash_profile中的环境变量设置:

ssh host1 -t ssh host2 -t bash -lc nvitop

5.8

数据备份

使用Kopia

5.5

注入基于webpack的网站

使用webpackTools

5.4

VS Code配置Vim插件通过快捷键复制整个文件

修改settings.json

    "vim.normalModeKeyBindingsNonRecursive": [
        {
            "before": ["<C-c>"],
            "after": [
                "m", "a", // mark current position
                "g","g","V","G", // select all
                "\"", "+", "y", // yank to system clipboard
                "`", "a" // return to original position
            ]
        }
    ]

5.3

快速grep

使用ripgrep

cargo install ripgrep
rg "pattern" .
rg -u "pattern" . # do not repect .gitignore

5.2

rime雾凇拼音自定义短语

修改~/.local/share/fcitx5/rime/custom_phrase.txt(针对全拼),双拼需要新建并修改custom_phrase_double.txtref

5.1

带文件名地批量查看文件

tail -n +1 *

magick批量转换图片

 magick mogrify -format png *.webp
 magick mogrify -format png -path pngs *.webp

4.18

VS Code拓展配置损坏修复

现象:打开VS Code发现所有拓展消失了,设置(UI)不能打开,报错Unterminated string in JSON at position xxxx

原因:定位到~/.vscode/extensions/extensions.json文件不完整,大概率是上次写入的时候恰好硬盘满了导致的损坏

解决:查询到issue给出的解决方案是关闭VS Code后删除~/.vscode/extensions下的extensions.json.init-default-profile-extensions。然而我这边没有后者,实测仅删除extensions.json后重新打开VS Code,恢复正常了。

4.8

命令行随机采样文件

shuf -n 1000 input.jsonl > output.jsonl

4.4

Gradio自动重载

使用gradio运行主程序即可:

# suppose: my_app.launch()
gradio main.py --demo-name=my_app

my_app变量名为demo时,该参数可省略。

4.2

无root本地编译安装ncurses以及zsh

zsh依赖ncurses,有时系统中未安装导致无法本地编译zsh。

wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.1.tar.gz
tar zxvf ncurses-6.1.tar.gz
cd ncurses-6.1
./configure --prefix=$HOME/.local --with-shared --without-debug --enable-widec
make -j
make install

注意zsh最新的release版本zsh-5.9还是2022年5月的版本,已经不与新版ncurses兼容。我们需要使用仓库中最新的源码:

git clone https://github.com/zsh-users/zsh.git --depth 1
cd zsh
autoconf
./configure --prefix=$HOME/.local
make -j
make test
make install

ref

无root安装m4和autoconf

m4:

wget https://ftp.gnu.org/gnu/m4/m4-latest.tar.gz
tar zxvf m4-latest.tar.gz
cd m4-*
./configure --prefix=$HOME/.local # can be customized
make -j
make install

autoconf:

wget https://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.xz
tar Jxvf autoconf-latest.tar.xz
cd autoconf-*
./configure --prefix=$HOME/.local # can be customized
make -j
make install

4.1

fcitx5-rime配色主题

rime的Windows和MacOS版本都有相应的主题配置文件:weasel.yamlsquirrel.yaml。但Linux下rime时挂在输入法框架ibus或fcitx下的,UI界面并不由rime实现。因此,自定义主题需要在fcitx中配置,可参考ref

不错的rime配置+词库

雾凇拼音

rime覆写配置

可以通过*.custom.yaml的方式给原先的配置打补丁,避免修改原配置导致同步上游不便。

例如,原本的default.yaml中存在:

menu:
  page_size: 5

可以在default.yaml同级目录创建default.custom.yaml

patch:
  "menu/page_size": 3

完整patch:

patch:
  "menu/page_size": 3
  "key_binder/bindings/+":
    - { when: has_menu, accept: bracketleft, send: Page_Up }
    - { when: has_menu, accept: bracketright, send: Page_Down }
  "key_binder/select_first_character": null
  "key_binder/select_last_character": null

3.28

监控Python进程状态

有时运行一个Python程序后无法获知其运行进展(因其日志输出过于简略或阻塞于未知原因),我们希望能在不修改代码/干涉其运行的条件下了解其当前调用栈。可以使用非侵入式profiler工具py-spy

yay -S py-spy
# or: cargo install py-spy

echo 0| sudo tee /proc/sys/kernel/yama/ptrace_scope # ensure the ptrace permission
# suppose the target program is `app.py`
py-spy dump --pid `pgrep -f app.py` # dump the call stack
py-spy top --pid `pgrep -f app.py` # show a top-like live view of functions

镜像源滚包缓慢

无论什么镜像源都不到3MB/s,经排查发现是默认解析到了ipv6,而校园网对ipv6存在限速。目前可以使用仅解析ipv4的地址。

3.12

共用同一个Linux user时简单隔离

有时没有创建新用户的权限,需要多人共用同一用户,可以在home下创建子目录作为隔离的home,并使用RemoteCommand指定:

/home/user
├── user1
│   └── init.sh
├── user2
│   └── init.sh
└── user3
    └── init.sh

init.sh:

#!/bin/bash
export HOME=/home/user/user1
export SHELL=zsh # can be customized

cd $HOME
exec $SHELL -l

SSH Config:

Host ...
  HostName ...
  User user
  RemoteCommand /home/user/user1/init.sh
  RequestTTY yes

curl&git证书问题

某些配置有问题的服务器上,CA根证书不存在或没有读权限,导致curl报错:

$ curl https://baidu.com
curl: (77) error setting certificate verify locations:
  CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
$ ls -al /etc/pki/tls/certs/ca-bundle.crt
lrwxrwxrwx 1 root root 49 Jun  1  2024 /etc/pki/tls/certs/ca-bundle.crt -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
$ ls -al /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
-rw------- 1 root root 209650 Nov 15 10:20 /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem

这种情况可以从curl官方下载CA Bundle证书到有权限的目录,并使用环境变量指定curl使用:

cd /path/to/save/certs
curl --etag-compare etag.txt --etag-save etag.txt --remote-name https://curl.se/ca/cacert.pem
export CURL_CA_BUNDLE=/path/to/save/certs/cacert.pem

同理,git出现相同证书问题也可以指定环境变量解决

export GIT_SSL_CAINFO=/path/to/save/certs/cacert.pem

对于其他程序(如rustup-init使用的reqwest库,SSL_CERT_FILE基本能相对通用地解决问题,这个环境变量对curl有效但对git无效)

export SSL_CERT_FILE=/path/to/save/certs/cacert.pem

3.7

对某目录递归字符串

grep -r "target" /path/to/grep/
grep -r "target" /path/to/grep/ --exclude="*.file.pattern.to.ignore"

2.25

重启docker daemon而不重启容器

首先添加live-restore配置:

/etc/docker/daemon.json:

{
    "live-restore": true,
    ...
}

使用SIGHUP信号触发dockerd重载配置:

sudo kill -SIGHUP $(pidof dockerd)
docker info | grep Live # 检查配置已载入,预期 Live Restore Enabled: true

重启daemon:

sudo systemctl restart docker

docker覆盖entrypoint

当Dockerfile为镜像指定了entrypoint时,docker run命令中指定的命令名会作为参数传递给entrypoint程序,可以使用--entrypoint new_cmd覆盖。

2.11

Ubuntu安装deb版firefox(非snap版)

source

1.8

uv安装有特殊要求的包

uv add flash-attn --no-build-isolation
uv add --editable ./path/to/package

切换CUDA版本

首选使用update-alternatives,如果不能使用,则可以通过指定环境变量的方式:

cuda_path="/usr/local/cuda-11.7" # or other

export CUDA_HOME="${cuda_path}"
export CUDA_ROOT="${cuda_path}"
export LD_LIBRARY_PATH="${cuda_path}/lib64:${cuda_path}/lib:${LD_LIBRARY_PATH}"
export PATH="${cuda_path}/bin:${PATH}"

uv安装PyTorch最佳实践

  1. 在系统中安装所需CUDA版本

  2. 根据PyTorch和CUDA版本需求,在PyTorch官网确定要使用的index

  3. pyproject.toml中添加相应源,并指定explicit = true使得仅torch相关包使用该源。 例如:

```toml [tool.uv.sources] torch = [{ index = "pytorch-index" }] torchvision = [{ index = "pytorch-index" }]

[[tool.uv.index]] url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" default = true

[[tool.uv.index]] name = "pytorch-index" url = "https://download.pytorch.org/whl/cu121" explicit = true ```

  1. 执行uv sync同步环境

ref

1.7

git打包文件

git可以将工作区打包为压缩包,只包含被跟踪的文件

git archive --output "./output.tar.gz" master # 文件类型通过--output自动推断

对Gradio应用进行反向代理

反代gradio应用时(例如example.com/gradio-demo -> localhost:7860),由于gradio无法感知到外部url路径,会给出错误的资源url,可以通过设置GRADIO_ROOT_PATH环境变量解决。ref

server {
    listen 80;
    server_name example.com www.example.com;  # Change this to your domain name

    location /gradio-demo/ {  # Change this if you'd like to server your Gradio app on a different path
        proxy_pass http://127.0.0.1:7860/; # Change this if your Gradio app will be running on a different port
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

1.6

Shell在管道中间复制一份到错误流

command1 | command2 # original
command1 | tee /dev/stderr | command2 # for debug

1.1

\(\text{The Best Year Ever!}\)