b3sum,速度可达到md5sum
的数十倍,且提供更强的安全性,比主打速度的xxh128sum
还快1倍
之前使用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-plugin支持将其他窗口作为插件渲染到锁屏界面上,注意需要借助windowtolayer
包将普通程序转换为使用wlr-layer-shell
协议渲染:
swaylock-plugin --command-each "windowtolayer -- alacritty -e btm" # `btm` can be customized
有时远程主机指纹发生变化,手动删除较为麻烦
ssh-keygen -R hostname
某些Python库需要使用Python头文件进行编译(如triton),可能会遭遇缺失Python.h
头文件的问题,这是由于uv在当前环境所需Python版本在系统中已安装时会优先使用系统中的版本,而系统版本不一定安装了头文件包(如libpython3.12-dev
)
uv python pin 3.12 --managed-python # 使用uv本地安装的python,自带头文件
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
cargo install miniserve
cd /path/to/serve
miniserve . --port <port>
curl localhost:port # check service
有时遇到上游源挂了无法安装某个包,但本地已有一个环境此前安装过,可以从这个环境中重新打包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
用于二分查找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之前的位置
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
(已在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 });
}
});
}
});
})();
使用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'
解决。
没有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
git branch -vv
文件系统模块自定义别名
原配置不支持设置别名,如果挂载的路径过长会比较难看,可以通过继承的方式分子模块自定义:
[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"
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
---
# 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"
使用chromedriver_autoinstaller
:
chromedriver_autoinstaller.install()
pyinstaller -F <entry.py> -n <output_exe_name> --add-data "<source_path>:<target_path>" -i <icon_path>
现在已经没几个靠谱的平台提供旧版本安装包了
打开高级配置编辑器,修改layout.css.devPixelsPerPx
属性值
有时需要在Notebook中指定环境变量(如CUDA_VISIBLE_DEVICES
)可以使用魔法命令:
%env CUDA_VISIBLE_DEVICES=2,3
(需要在import torch
之前执行)
有时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"
}
之前写“共用同一个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登录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
使用Kopia
修改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
]
}
]
使用ripgrep:
cargo install ripgrep
rg "pattern" .
rg -u "pattern" . # do not repect .gitignore
修改~/.local/share/fcitx5/rime/custom_phrase.txt
(针对全拼),双拼需要新建并修改custom_phrase_double.txt
。ref
tail -n +1 *
magick mogrify -format png *.webp
magick mogrify -format png -path pngs *.webp
现象:打开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,恢复正常了。
shuf -n 1000 input.jsonl > output.jsonl
使用gradio
运行主程序即可:
# suppose: my_app.launch()
gradio main.py --demo-name=my_app
当my_app
变量名为demo
时,该参数可省略。
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
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
rime的Windows和MacOS版本都有相应的主题配置文件:weasel.yaml
和squirrel.yaml
。但Linux下rime时挂在输入法框架ibus或fcitx下的,UI界面并不由rime实现。因此,自定义主题需要在fcitx中配置,可参考ref。
可以通过*.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
有时运行一个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的地址。
有时没有创建新用户的权限,需要多人共用同一用户,可以在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
某些配置有问题的服务器上,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
grep -r "target" /path/to/grep/
grep -r "target" /path/to/grep/ --exclude="*.file.pattern.to.ignore"
首先添加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
当Dockerfile为镜像指定了entrypoint时,docker run
命令中指定的命令名会作为参数传递给entrypoint程序,可以使用--entrypoint new_cmd
覆盖。
uv add flash-attn --no-build-isolation
uv add --editable ./path/to/package
首选使用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}"
-
在系统中安装所需CUDA版本
-
根据PyTorch和CUDA版本需求,在PyTorch官网确定要使用的index
-
在
pyproject.toml
中添加相应源,并指定explicit = true
使得仅torch
相关包使用该源。 例如:[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
-
执行
uv sync
同步环境
git可以将工作区打包为压缩包,只包含被跟踪的文件
git archive --output "./output.tar.gz" master # 文件类型通过--output自动推断
反代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;
}
}
command1 | command2 # original
command1 | tee /dev/stderr | command2 # for debug