#!/usr/bin/env bashset -eecho "=============================="echo " Linux Workstation Setup (Interactive Final)"echo "=============================="confirm() {read -rp "$1 (y/n): " ans [[ "$ans" == "y" || "$ans" == "Y" ]]}=========================================================1. ZSH + OH-MY-ZSH=========================================================if confirm "[1/5] 安装 zsh + oh-my-zsh + 设置默认 shell"; thensudo apt update sudo apt install -y zsh curl git xdg-user-dirs wget if [ ! -d "$HOME/.oh-my-zsh" ]; then RUNZSH=no CHSH=no KEEP_ZSHRC=yes \ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" fi if [ "$SHELL" != "$(which zsh)" ]; then chsh -s "$(which zsh)" || true fi echo "✔ ZSH 完成"elseecho "✘ 跳过 ZSH"fi=========================================================2. PROXY (proxy on/off)=========================================================if confirm "[2/5] 配置 proxy (proxy on / proxy off)"; thenread -rp "请输入代理地址 (如 http://192.168.1.78:4780): " PROXY_URL if [ -n "$PROXY_URL" ]; then cat > ~/.proxy.zsh << EOF=========================Proxy CLI=========================PROXY_URL="$PROXY_URL"proxy() {case "\$1" in on) export http_proxy="\$PROXY_URL" export https_proxy="\$PROXY_URL" export all_proxy="\$PROXY_URL" export no_proxy="localhost,127.0.0.1,::1" git config --global http.proxy "\$PROXY_URL" git config --global https.proxy "\$PROXY_URL" echo "[proxy] ON -> \$PROXY_URL" ;; off) unset http_proxy https_proxy all_proxy no_proxy git config --global --unset http.proxy 2>/dev/null || true git config --global --unset https.proxy 2>/dev/null || true echo "[proxy] OFF" ;; *) echo "Usage:" echo " proxy on" echo " proxy off" ;; esac}EOF if ! grep -q "proxy.zsh" ~/.zshrc; then echo "source ~/.proxy.zsh" >> ~/.zshrc fi echo "✔ Proxy 完成" else echo "✘ 未输入 proxy，跳过" fielseecho "✘ 跳过 proxy"fiif confirm "[3/5] 切换英文用户目录 + 迁移 + 删除旧中文目录"; thensudo apt install -y xdg-user-dirs rsync # ===================================================== # 1. 强制切换为英文 XDG # ===================================================== LANG=en_US.UTF-8 xdg-user-dirs-update --force echo "已切换为英文用户目录" # ===================================================== # 2. 中文 -> 英文映射 # ===================================================== declare -A MAP=( ["桌面"]="Desktop" ["下载"]="Downloads" ["文档"]="Documents" ["图片"]="Pictures" ["音乐"]="Music" ["视频"]="Videos" ["公共"]="Public" ["模板"]="Templates" ) echo "开始迁移文件..." for zh in "${!MAP[@]}"; do en="${MAP[$zh]}" src="$HOME/$zh" dst="$HOME/$en" if [ -d "$src" ]; then mkdir -p "$dst" echo "迁移: $src -> $dst" # 安全复制（不覆盖已有文件） rsync -a --ignore-existing "$src/" "$dst/" echo "完成: $zh → $en" fi done echo "迁移完成，开始删除旧目录..." # ===================================================== # 3. 删除旧中文目录（关键步骤） # ===================================================== for zh in "${!MAP[@]}"; do src="$HOME/$zh" if [ -d "$src" ]; then echo "删除: $src" rm -rf "$src" fi done echo "====================================" echo "完成：中文目录已迁移并删除" echo "建议重新登录会话" echo "====================================" elseecho "跳过目录迁移"fi=========================================================4. GO (国内镜像 + fallback)=========================================================if confirm "[4/5] 安装 Golang（国内镜像）"; thenGO_VERSION="1.22.5" GO_TAR="go${GO_VERSION}.linux-amd64.tar.gz" cd /tmp echo "尝试国内镜像下载..." if ! wget -q https://mirrors.aliyun.com/golang/$GO_TAR; then echo "阿里云失败，切换官方源..." wget -q https://go.dev/dl/$GO_TAR fi sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf $GO_TAR if ! grep -q "/usr/local/go/bin" ~/.zshrc; then cat >> ~/.zshrc << 'EOF' Goexport PATH=$PATH:/usr/local/go/bin:$HOME/go/binEOFfi echo "✔ Go 完成"elseecho "✘ 跳过 Go"fi=========================================================5. NVM + NODE=========================================================if confirm "[5/5] 安装 nvm + node"; thenexport NVM_DIR="$HOME/.nvm" if [ ! -d "$NVM_DIR" ]; then curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash fi if ! grep -q "nvm.sh" ~/.zshrc; then cat >> ~/.zshrc << 'EOF' NVMexport NVM_DIR="$HOME/.nvm"[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"EOFfi echo "✔ NVM 完成"elseecho "✘ 跳过 NVM"fi=========================================================echo "=============================="echo "全部完成"echo "请执行：source ~/.zshrc"echo "=============================="
Linux + Ghostty + fcitx5 + Rime 全流程踩坑指南(含搜狗迁移 & Lua 问题)
我把 Linux 输入法从搜狗换成 Rime，顺手踩了几个坑最近换了个终端，用的是 Ghostty，然后发现一个很现实的问题：
原文 https://www.bilibili.com/opus/890449778240913446安装后直接一波# !/bin/bash rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5Core.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5Core.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5Gui.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5Gui.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5Widgets.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5Widgets.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5DBus.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5DBus.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5DBus.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5Qml.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5Qml.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5Qml.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5Network.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5Network.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5Network.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5Quick.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5Quick.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5QuickWidgets.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5QuickWidgets.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5QuickWidgets.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5Svg.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5Svg.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5Svg.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libQt5XcbQpa.so.5 ln -s /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5 /opt/sogoupinyin/files/lib/qt5/lib/libQt5XcbQpa.so.5 rm /opt/sogoupinyin/files/lib/qt5/lib/libFcitxQt5DBusAddons.so.1 ln -s /usr/lib/x86_64-linux-gnu/libFcitxQt5DBusAddons.so.1 /opt/sogoupinyin/files/lib/qt5/lib/libFcitxQt5DBusAddons.so.1 rm /opt/sogoupinyin/files/lib/qt5/lib/libgsettings-qt.so.1 ln -s /usr/lib/x86_64-linux-gnu/libgsettings-qt.so.1 /opt/sogoupinyin/files/lib/qt5/lib/libgsettings-qt.so.1 rm /opt/sogoupinyin/files/lib/qt5/lib/libpcre.so.3 ln -s /usr/lib/x86_64-linux-gnu/libpcre.so.3 /opt/sogoupinyin/files/lib/qt5/lib/libpcre.so.3 # plugins rm /opt/sogoupinyin/files/lib/qt5/plugins/iconengines/libqsvgicon.so ln -s /usr/lib/x86_64-linux-gnu/qt5/plugins/iconengines/libqsvgicon.so /opt/sogoupinyin/files/lib/qt5/plugins/iconengines/libqsvgicon.so rm /opt/sogoupinyin/files/lib/qt5/plugins/imageformats/libqsvg.so ln -s /usr/lib/x86_64-linux-gnu/qt5/plugins/imageformats/libqsvg.so /opt/sogoupinyin/files/lib/qt5/plugins/imageformats/libqsvg.so rm /opt/sogoupinyin/files/lib/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so ln -s /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so /opt/sogoupinyin/files/lib/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so rm /opt/sogoupinyin/files/lib/qt5/plugins/platforms/libqlinuxfb.so ln -s /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqlinuxfb.so /opt/sogoupinyin/files/lib/qt5/plugins/platforms/libqlinuxfb.so rm /opt/sogoupinyin/files/lib/qt5/plugins/platforms/libqminimal.so ln -s /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqminimal.so /opt/sogoupinyin/files/lib/qt5/plugins/platforms/libqminimal.so rm /opt/sogoupinyin/files/lib/qt5/plugins/platforms/libqoffscreen.so ln -s /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqoffscreen.so /opt/sogoupinyin/files/lib/qt5/plugins/platforms/libqoffscreen.so rm /opt/sogoupinyin/files/lib/qt5/plugins/platforms/libqxcb.so ln -s /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqxcb.so /opt/sogoupinyin/files/lib/qt5/plugins/platforms/libqxcb.so rm /opt/sogoupinyin/files/lib/qt5/plugins/xcbglintegrations/libqxcb-glx-integration.so ln -s /usr/lib/x86_64-linux-gnu/qt5/plugins/xcbglintegrations/libqxcb-glx-integration.so /opt/sogoupinyin/files/lib/qt5/plugins/xcbglintegrations/libqxcb-glx-integration.so
环境变量设置：CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 为 1 解决
USE information_schema; SELECT T.TABLE_NAME as '表名', T.TABLE_COMMENT as '表说明', C.COLUMN_NAME AS '字段名', C.COLUMN_COMMENT AS '字段说明', C.COLUMN_TYPE AS '数据类型', C.IS_NULLABLE AS '允许为空', C.EXTRA AS '其他属性' FROM COLUMNS C INNER JOIN TABLES T ON C.TABLE_SCHEMA = T.TABLE_SCHEMA AND C.TABLE_NAME = T.TABLE_NAME WHERE T.TABLE_SCHEMA = '表名'
这几天公司又有人在吵吵把某些业务从php转到java，我没怎么说话，虽然我不统同意，但是我还是没说话。第一，现在公司所处的阶段，非语言的切换所能解决的。现在公司的发展遇到瓶颈，业务流程不规范，很多业务因为变革阶段所带来的流程缺失亟待解决。比如之前客服反馈工单系统，当一个人下班之后，需要另外一个人越权登录下班的伙伴的账号才可以继续操作什么的。如此这般的业务上的确实还有许许多多，所以我认为，在现有技术栈能满足我们开发需要的情况下，当务之急是，“好快准”的去迭代我们的业务功能，满足也无需要，进而满足用户的需要。第二，公司现有的技术栈，不是特别适合去切换java，因为公司现有的业务线，很多还是php的，也有大量的php人员。如果切换，这些人怎么办。众所周知，java的学习成本还是很高的，而且现在的开发人员基础差，底层差，很难在短时间内（半年），完全由php切换到java。所以哎，话说，不管java还是php或许，其他，路是自己走的，
# import traceback # # for a in traceback.format_stack(): # print(a)
最近php在和java做通信的时候，java返回了一个字符串如下：eyJleHAiOjE1NTI2Mzc2MTgsInVzZXIiOnsidWlkIjoxNDgzNzQzLCJhY0lkIjozMTMyMTU5MTIwNjg4NDM5MCwibmFtZSI6Iui_mzEifSwiaWF0IjoxNTUwMDQ1NjE4fQ php提示解析失败，然后线上的解析工具都解析不出来，按照java的说法，是先需要一次urldecode之后才可然后尝试urldecode，但是在php中失败，在线的urldecode解析失败。相当费解，但是因为这是一个jwt串的payload部分，进而使用jwt.io的在线解析工具尝试，成功.....翻看jwt.io官方提供的php demo，看到如下代码：public static function urlsafeB64Decode($input) { $remainder = strlen($input) % 4; if ($remainder) { $padlen = 4 - $remainder; $input .= str_repeat('=', $padlen); } return base64_decode(strtr($input, '-_', '+/')); } 进而查阅文档，解释如下：原因之1：Base64编码要求把3个8位字节（3X8=24）转化为4个6位的字节（4X6=24），之后在6位的前面补两个0，形成8位一个字节的形式。 如果剩下的字符不足3个字节，则用0填充，输出字符使用'='，因此编码后输出的文本末尾可能会出现1或2个'='。所以有了第一段代码：$remainder = strlen($input) % 4; if ($remainder) { $padlen = 4 - $remainder; $input .= str_repeat('=', $padlen); }但是在很多文章里说，不要等号也不邮箱。测试了，确实如此，但是为什么java返回的值缺了几个等号，就不知道了。原因之2：由于标准的Base64编码后可能出现字符+和/，在URL中就不能直接作为参数，所以又有一种"url safe"的base64编码，其实就是把字符+和/分别变成-和_然后翻阅php手册的base64函数，也有相关的介绍：Base64 for URL parameters/filenames, that adhere to RFC 4648. Defaultsto dropping the padding on encode since it's not required fordecoding, and keeps the URL free of % encodings.<?php function base64url_encode($data, $pad = null) {$data = str_replace(array('+', '/'), array('-', '_'), base64_encode($data)); if (!$pad) { $data = rtrim($data, '='); } return $data; } function base64url_decode($data) { return base64_decode(str_replace(array('-', '_'), array('+', '/'), $data)); }所以说我上面的串中有下划线，自然解析不出来了。就有了jwt的demo中的base64_decode(strtr($input, '-_', '+/'));这两个问题导致了和java之间的一些争议，java反复告诉我，因为他们用了urlencode，所以只需要urldecode就可以了。但是php中始终失败。这里面其实是java的一个误区把，他们使用了一个叫Base64.GetUrlDecode().decode()的方法进行解密，相应的方法进行加密。然后告诉我直接使用urldecode就可以。但是实际上Base64.GetUrlDecode这里的urldecode只是一个base64的“url safe”的加解密方式，并不是我们通常意义上的urldecode和urlencode，我猜测这个Base64.GetUrlDecoded的底层应该也只是一个字符串的替换。终上所述。补齐等号，替换掉横杠下划线，这个问题得到解决。很多时候因为不同语言对一些基础的加解密或者编码的处理还是有一些不一样的，一旦没理解清楚，容易踩坑。