Ubuntu Software

Collection of useful software for Ubuntu.

  • Google-PinYin

    The best choice for Chinese input. Although Sougou Input is aviailable, it will make your system slow, especially when you restart your system.

  • Wechat

    Based on wine, it can be used to install wechat on Ubuntu. In spite of defects, it is a good choice for Chinese users.

  • Clash Verge

    After clash for windows, it is recommended to use clash verge.

  • Tmux

    An incrediable tool of split-screen.

  • Docker

  • Pycharm

  • VIM Clipboard

sudo apt install -y vim-gtk3 highlight bat ripgrep tree net-tools nmap

Install Google-PinYin

On Ubuntu, Google-PinYin based on Fcitx. So install Fcitx firstly.

sudo apt install fcitx

Configure Fcitx

im-config

Install Google-PinYin

sudo apt install fcitx-googlepinyin

Running Fcitx

fcitx-config-gtk3

Wechat Install

Install Deepin Repository

wget -O- https://deepin-wine.i-m.dev/setup.sh | sh

Install Wechat

sudo apt install com.qq.weixin.deepin

解决统信应用解压失败的问题

sudo vim /opt/deepinwine/tools/run_v4.sh

# find this line
7z x "$APPDIR/$APPTAR" -o"$1"
# update it following line
7z x "$APPDIR/$APPTAR" -o"$1" || true

Remove Wechat

sudo apt remove com.qq.weixin.deepin

Delete Deepin Repository

sudo rm /etc/apt/sources.d.list/deepin-wine.i-m.dev.list

Tencent Official Wechat

https://linux.weixin.qq.com/

  1. Download
wget https://dldir1v6.qq.com/weixin/Universal/Linux/WeChatLinux_x86_64.deb

Install Clash-Verge

clash-verge Project Github

https://github.com/clash-verge-rev/clash-verge-rev

Sloved Error of "clash-verge 依赖于 libwebkit2gtk-4.0-37."

sudo vim /etc/apt/sources.list.d/ubuntu.sources

# 添加以下内容
Types: deb
URIs: http://br.archive.ubuntu.com/ubuntu/
Suites: jammy
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

sudo apt update

Sloved Error of starting "clash-verge" but no display window

vim /usr/share/applications/clash-verge.desktop 

# 将 Exec 改为:
Exec=env WEBKIT_DISABLE_COMPOSITING_MODE=1 clash-verge

Clash For Linux

Github Repo

https://github.com/wnlen/clash-for-linux.git

Installation

git clone https://github.com/wnlen/clash-for-linux.git

Modify .env

The CLASH_URL is your subscription address, and the CLASH_SECRET is your password, when you login with web, you will use it.

Start Clash

sudo bash start.sh

As show tips, exec cmds.

Else CMD

  • Close clash
sudo bash shutdown.sh
  • Close proxy
proxy-off

Install Docker

Install Official Docker GPG Key

sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

Add Official Docker Repo

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Update Package Lists

sudo apt-get update

Install Docker

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Well, you can access https://download.docker.com/ and download the .deb file manually.

Such Path: https://download.docker.com/linux/ubuntu/dists/focal/pool/stable/amd64/

Crack Pycharm

Edit vmoptions

vim /pycharm/install/path/bin/pycharm64.vmoptions

Add following options to the end of the file

-javaagent:/jar-package/path/jetbra/ja-netfilter.jar=jetbrains
--add-opens=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
--add-opens=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED

Activation Code

YQLSN55KLT-eyJsaWNlbnNlSWQiOiJZUUxTTjU1S0xUIiwibGljZW5zZWVOYW1lIjoi5rC45LmF5Zyw5Z2AIHd3d8K3YWppaHVvwrdjb20iLCJsaWNlbnNlZVR5cGUiOiJQRVJTT05BTCIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiIiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IkdPIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSUzAiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRNIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjAyNS0wMy0xMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNVIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSU0MiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRTIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSRCIsInBhaWRVcFRvIjoiMjAyNS0wMy0xMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUUEiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSU0YiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUk0iLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IklJIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJEUE4iLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRCIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJEQyIsInBhaWRVcFRvIjoiMjAyNS0wMy0xMSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUFMiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJSIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSU1YiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiV1MiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlBTSSIsInBhaWRVcFRvIjoiMjAyNS0wMy0xMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQQ1dNUCIsInBhaWRVcFRvIjoiMjAyNS0wMy0xMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJBSUwiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJTIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IkRQIiwicGFpZFVwVG8iOiIyMDI1LTAzLTExIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBEQiIsInBhaWRVcFRvIjoiMjAyNS0wMy0xMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUlIiLCJwYWlkVXBUbyI6IjIwMjUtMDMtMTEiLCJleHRlbmRlZCI6dHJ1ZX1dLCJtZXRhZGF0YSI6IjAyMjAyNTAyMTJQUEFNMDA2MDA1QSIsImhhc2giOiI2NjM5MzE5MS8wOjc2MDEyODIxNCIsImdyYWNlUGVyaW9kRGF5cyI6NywiYXV0b1Byb2xvbmdhdGVkIjpmYWxzZSwiaXNBdXRvUHJvbG9uZ2F0ZWQiOmZhbHNlLCJ0cmlhbCI6ZmFsc2UsImFpQWxsb3dlZCI6dHJ1ZX0=-HhxiOkGKCb3ymp+pacIhMlNE/54EGAr0LE2Qu7IBbQFZjk144sEBxR8JB3ZXyp6L1S5ruxTVpORLqQXLBrfH5m3Y7llwnp0DXPrvFLmPnYU1GnROYxpdGWZO3Tl8DpYu4uFQEY1AWkZXcy4TonPGkChktneR/7Z04tKapCFMbomkuEGb8d73c3Sviv40j1QbhKRaBlGhUUFcto9oJPl7cUf/i8Tz9FQgqdZvxpWtFgK7IeDh2N2b5AJvKH6UJadPjLYeI55r6aRNnvdyQHRTUmWvvSRO3CxNGdEeOp5YPR7pdUStvigYD+0Ww6lUuv4BB5BRY26ale5djLaBHoL7BA==-MIIETDCCAjSgAwIBAgIBETANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTI0MDkyMDEyMTEyN1oXDTI2MDkyMjEyMTEyN1owHzEdMBsGA1UEAwwUcHJvZDJ5LWZyb20tMjAyNDA5MjAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7SH/XcUoMwkDi8JJPzXWWHWFdOZdrP2Dqkz2W8iUi650cwz2vdPEd0tMzosLAj7ifkFEHUyiuEcL//q9d9Op7ZsV23lpPXX8tFMLFwugoQ9D8jDLT/XP9pp/YukWkKF5jpNbaCvsVQkDdYkArBkYvhH3aN4v9BkEsXahfgLLOPe4IG2FDJNf9R4to9V1vt+m2UVJB0zV4a/sVMKUZLgqKmKKKOKoLrE3OjBlZlb+Q0z2N5dsW0hDEVRFGmBUAbHN/mp44MMMvEIFKfoLIGpgic92P2O6uFh75PI7mcultL6yuR48ajErx8CjjQEGOSnoq/8hD+yVE+6GW2gJa2CPvAgMBAAGjgZkwgZYwCQYDVR0TBAIwADAdBgNVHQ4EFgQUb5NERj05GyNerQ/Mjm9XH8HXtLIwSAYDVR0jBEEwP4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0GCCQDSbLGDsoN54TATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBALq6VfVUjmPI3N/w0RYoPGFYUieCfRO0zVvD1VYHDWsN3F9buVsdudhxEsUb8t7qZPkDKTOB6DB+apgt2ZdKwok8S0pwifwLfjHAhO3b+LUQaz/VmKQW8gTOS5kTVcpM0BY7UPF8cRBqxMsdUfm5ejYk93lBRPBAqntznDY+DNc9aXOldFiACyutB1/AIh7ikUYPbpEIPZirPdAahroVvfp2tr4BHgCrk9z0dVi0tk8AHE5t7Vk4OOaQRJzy3lST4Vv6Mc0+0z8lNa+Sc3SVL8CrRtnTAs7YpD4fpI5AFDtchNrgFalX+BZ9GLu4FDsshVI4neqV5Jd5zwWPnwRuKLxsCO/PB6wiBKzdapQBG+P9z74dQ0junol+tqxd7vUV/MFsR3VwVMTndyapIS+fMoe+ZR5g+y44R8C7fXyVE/geg+JXQKvRwS0C5UpnS5FcGk+61b0e4U7pwO20RlwhEFHLSaP61p2TaVGo/TQtT/fWmrtV+HegAv9P3X3Se+xIVtJzQsk8QrB/w52IB3FKiAKl/KRn1egbMIs4uoNAkqNZ9Ih2P1NpiQnONFmkiAgeynJ+0FPykKdJQbV3Mx44jkaHIif4aFReTsYX1WUBNu/QerZRjn4FVSHRaZPSR5Oi82Wz0Nj7IY9ocTpLnXFrqkb/Kt3S6B9s2Kol3Lr1ElYA

Start Pycharm like VS-Code

Modify pycharm.sh

Generally pycharm.sh is located at /pycharm/install/path/bin/pycharm.sh.

Add > /dev/null 2>&1 & to the end of the file. Make sure the file looks like this:

  com.intellij.idea.Main \
  "$@" \
  > /dev/null 2>&1 &
sudo ln -sf /pycharm/install/path/bin/pycharm.sh /usr/local/bin/pycharm

Then, you can start Pycharm by typing pycharm in the terminal.

knight@Lenovo:~/workspace/game_of_thrones$ pycharm .
knight@Lenovo:~/workspace/game_of_thrones$

Tmux

Installation

https://github.com/tmux/tmux

sudo apt install -y tmux

Install Tmux Plugins Manager

https://github.com/tmux-plugins/tpm

git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm

Create .tmux.conf File

This is my personal tmux config file.

{{#include ./mdbook-files/tmux.conf}}

Install Nerd Font

Nerd Github Repo

  1. Clone Repo to install

Get script of install Nerd fonts. After many attempts, Font Meslo performed best.

git clone --depth 1 https://github.com/ryanoasis/nerd-fonts.git && \
cd nerd-fonts/ && \
./install.sh Meslo
  1. Use script to install (Recommend)
wget https://raw.githubusercontent.com/mcarvalho1/Simple-NerdFonts-Downloader/c7854dae2153aa199277926bed4b992488b65a3d/nf_downloader.sh

nf_downloader.sh default will install all fonts, remember to modify it. The fonts will save in ~/.local/share/fonts.

Create WindTerm Desktop Entry

[Desktop Entry]
Name=WindTerm
Comment=A professional cross-platform SSH/Sftp/Shell/Telnet/Serial terminal
GenericName=Connect Client
Exec=/home/knight/windTerm/WindTerm_2.6.1/WindTerm
Type=Application
Icon=/home/knight/windTerm/WindTerm_2.6.1/windterm.png
StartupNotify=false
StartupWMClass=Code
Categories=Application;Development
Actions=new-empty-window
Keywords=windterm

[Desktop Action new-empty-window]
Name=New Empty Window
Exec=/home/knight/windTerm/WindTerm_2.6.1/WindTerm
Icon=/home/knight/windTerm/WindTerm_2.6.1/windterm.png

Asciiquarium Command Install

Ubuntu

sudo apt-get install -y perl libcurses-perl wget
wget http://search.cpan.org/CPAN/authors/id/K/KB/KBAUCOM/Term-Animation-2.4.tar.gz
wget http://www.robobunny.com/projects/asciiquarium/asciiquarium.tar.gz
tar -xf Term-Animation-2.4.tar.gz
tar -xf asciiquarium.tar.gz
cd Term-Animation-2.4/ && perl Makefile.PL && make && sudo make install
cd ../asciiquarium_1.1/
cp asciiquarium /usr/local/bin
sudo chmod +x /usr/local/bin/asciiquarium
asciiquarium

Centos

cd /opt
yum install -y wget
wget http://search.cpan.org/CPAN/authors/id/K/KB/KBAUCOM/Term-Animation-2.4.tar.gz
tar xf Term-Animation-2.4.tar.gz
yum install perl-Curses.x86_64  -y
yum install perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker  -y
cd /opt/Term-Animation-2.4/  && perl Makefile.PL
make
make install
cd /opt
wget http://www.robobunny.com/projects/asciiquarium/asciiquarium.tar.gz
tar -zxvf asciiquarium.tar.gz
cd asciiquarium_1.1/
cp asciiquarium /usr/local/bin
chmod +x /usr/local/bin/asciiquarium
asciiquarium

使用 frp

Project Official Website

https://github.com/fatedier/frp

中文文档

SSH Service

The server configuration

vim frps.toml
bindPort = 5432  # frp 建立通讯的端口
auth.token = "123456"

The Client configuration

vim frpc.toml
serverAddr = "123.00.00.01"
serverPort = 5432   # frp 建立通讯的端口
auth.token = "123456"

[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 10086   # frp 映射的端口,VPS需要打开的端口

FTP Service

The Server configuration

vim frps.toml
bindPort = 5432
auth.token = "123456"

The Client configuration

vim frpc.toml
serverAddr = "123.00.00.01"
serverPort = 5432
auth.token = "123456"

[[proxies]]
name = "test_static_file"
type = "tcp"
localPort = 21
remotePort = 10086

[proxies.plugin]
type = "static_file"

# 本地文件目录,对外提供访问
localPath = "/your/local/path"

# URL 中的前缀,将被去除,保留的内容即为要访问的文件路径
stripPrefix = "static"
httpUser = "user"
httpPassword = "password"

systemctl Configuration

  • frps | Server configuration
sudo vim /etc/systemd/system/frps.service
[Unit]
# 服务名称,可自定义
Description = frp server
After = network.target syslog.target
Wants = network.target
[Service]
Type = simple
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart = /root/frp/frps -c /root/frp/config.toml
[Install]
WantedBy = multi-user.target

reload daemon and start service

sudo systemctl daemon-reload
sudo systemctl enable --now frps
  • frpc | Client configuration
sudo vim /etc/systemd/system/frpc.service
[Unit]
Description=FRPC Client Service
After=network.target

[Service]
User=knight
Group=knight
Type=simple
ExecStart=/home/knight/frp/frpc -c /home/knight/frp/config.toml
Restart=on-failure
RestartSec=5s
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=frpc

[Install]
WantedBy=multi-user.target

reload daemon and start service

sudo systemctl daemon-reload
sudo systemctl enable --now frpc

Entertainment

Install KODI

https://kodi.tv/download/

sudo apt install software-properties-common
sudo add-apt-repository -y ppa:team-xbmc/ppa
sudo apt install kodi

Install TMM

https://www.tinymediamanager.org/download/

qBittorrent Enhanced

https://github.com/c0re100/qBittorrent-Enhanced-Edition/releases

LX Music

https://github.com/lyswhut/lx-music-desktop/releases

ZSH

zsh is a shell that can be used as a replacement for bash.

Installation

https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH

sudo apt install zsh

Configuration

chsh -s $(which zsh) $USER

Make it works, you can logout system and relogin again.

zsh & oh-my-zsh

Git repo

https://github.com/ohmyzsh/ohmyzsh

Installation

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

The default location is ~/.oh-my-zsh (hidden in your home directory, you can access it with cd ~/.oh-my-zsh)

Manual Installation

If you want to change the location, you can do so by setting the ZSH environment variable before installing:

Firstly, install the install script:

wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh

Secondly, setting the install path run the install script, if you want to install oh-my-zsh to $HOME/awesome-shell/oh-my-zsh:

ZSH="$HOME/awesome-shell/oh-my-zsh" sh install.sh

powerlevel10K

https://github.com/romkatv/powerlevel10k.git

Installation

  1. Clone repo into oh-my-zsh custom themes path:
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
  1. Modify .zshrc:
ZSH_THEME="powerlevel10k/powerlevel10k"
  1. Exit terminal and reopen it.

zsh-autosuggestions

https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md

Installation

  1. Clone this repository into $ZSH_CUSTOM/plugins (by default ~/.oh-my-zsh/custom/plugins)
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
  1. Add the plugin to the list of plugins for Oh My Zsh to load (inside ~/.zshrc):
plugins=( 
    # other plugins...
    zsh-autosuggestions
)

zsh-autocomplete

https://github.com/marlonrichert/zsh-autocomplete

Installation

  1. Clone this repository into $ZSH_CUSTOM/plugins (by default ~/.oh-my-zsh/custom/plugins)
git clone --depth 1 -- https://github.com/marlonrichert/zsh-autocomplete.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
  1. Add the plugin to the list of plugins for Oh My Zsh to load (inside ~/.zshrc):
plugins=( 
    # other plugins...
    zsh-autocomplete
)

zsh-syntax-highlighting

https://github.com/zsh-users/zsh-syntax-highlighting

Installation

    1. Clone this repository into $ZSH_CUSTOM/plugins (by default ~/.oh-my-zsh/custom/plugins)
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
  1. Add the plugin to the list of plugins for Oh My Zsh to load (inside ~/.zshrc):
plugins=(
    # ...
    zsh-syntax-highlighting
)

zsh-you-should-use

Installation

  1. Clone the repo into your oh-my-zsh plugins directory.
git clone https://github.com/MichaelAquilina/zsh-you-should-use.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/you-should-use
  1. Add you-should-use to the list of plugins in your ~/.zshrc file.
plugins=(
    # other plugins...
    you-should-use
)

zsh-ollama-completion

https://github.com/Katrovsky/zsh-ollama-completion

Installation

  1. Clone this repository into $ZSH_CUSTOM/plugins (by default ~/.oh-my-zsh/custom/plugins)
git clone https://github.com/Katrovsky/zsh-ollama-completion.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/ollama
  1. Add the plugin to the list of plugins for Oh My Zsh to load (inside ~/.zshrc):
plugins=(
    # ...
    ollama
)

Custom Plugins

Auto-activate Virtual Environments in Python Projects

  1. Clone this repository into $ZSH_CUSTOM/plugins (by default ~/.oh-my-zsh/custom/plugins)
git clone https://github.com/lxp731/auto-venv $ZSH_CUSTOM/plugins/auto-venv
  1. Add auto-venv to the plugins array in your ~/.zshrc file
plugins=(
    ...
    auto-venv
)

custom themes

  1. Clone this repo into ${ZSH_CUSTMO}/themes
git clone --depth 1 https://github.com/lxp731/zsh-custom-themes.git ${ZSH_CUSTOM}/themes
  1. Modify the following to your ~/.zshrc:
ZSH_THEME="awesome"

ENV Variable Setting

In Linux, environment variables are used to store information that can be used by programs when they are executed. They play a important role in Linux system.

.bashrc Configuration

# 设置shell命令查找
set -o vi

# 设置Ctrl+L清屏
bind -x '"\C-l":clear'

# helm complete
source <(helm completion bash)
source <(kubectl completion bash)

# alias kubectl & setting completion
alias k=kubectl
complete -o default -F __start_kubectl k

# highlight version cat
alias dog='highlight -O ansi'

# more high-level cat
alias cat='batcat'

# fzf change git branch
alias gcb="git branch | fzf --preview 'git show --color=always {-1}' \
                 --bind 'enter:become(git checkout {-1})' \
                 --height 60% --layout reverse"

# Auto-activate uv venv
PROJECT_PATH=""
CURRENT_PATH=""

auto_activate() {
  local NEW_PATH=$(pwd)

  # 只有在路径改变时才进行检查
  if [[ "$NEW_PATH" != "$CURRENT_PATH" ]]; then
    CURRENT_PATH="$NEW_PATH"

    if [[ -z "$PROJECT_PATH" ]]; then
      if [ -d ".venv" ]; then
        source .venv/bin/activate
        PROJECT_PATH="$CURRENT_PATH"
      fi
    else
      if [[ "$CURRENT_PATH" == "$PROJECT_PATH"* ]]; then
        return
      else
        if [[ -n "$VIRTUAL_ENV" ]]; then
          deactivate
        fi
        PROJECT_PATH=""
      fi
    fi
  fi
}

PROMPT_COMMAND=auto_activate

Modify .user-dirs.dirs

Update the Contents

XDG_DESKTOP_DIR="$HOME/desktop"
XDG_DOCUMENTS_DIR="$HOME/document"
XDG_DOWNLOAD_DIR="$HOME/download"
XDG_MUSIC_DIR="$HOME/music"
XDG_PICTURES_DIR="$HOME/picture"
XDG_PUBLICSHARE_DIR="$HOME/public"
XDG_TEMPLATES_DIR="$HOME/template"
XDG_VIDEOS_DIR="$HOME/video"

Update the Folder Names of Home Path

mv 桌面/ desktop
mv 文档/ document
mv 下载/ download
mv 音乐/ music
mv 图片/ picture
mv 公共/ public
mv 模板/ template
mv 视频/ video

Reboot

reboot

Vim Plugin Manager

Official Website

https://github.com/junegunn/vim-plug?tab=readme-ov-file

Install vim-plug

curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

Modify .vimrc

Add the following content:

call plug#begin('~/.vim/plugged')

" List your plugins here
Plug 'tpope/vim-sensible'

call plug#end()

You can add any plugins in the middle of call plug.

Reload the file or restart Vim, then you can:

  • :PlugInstall to install the plugins
  • :PlugUpdate to install or update the plugins
  • :PlugDiff to review the changes from the last update
  • :PlugClean to remove plugins no longer in the list

Confgure .vimrc

My .vimrc

"===
"===编写脚本自动插入
"===
function  AddTitleForShell()
   call append(0,"#!/bin/bash")
   call append(1,"# **********************************************************")
   call append(2,"# * Author        : Burgess Leo")
   call append(3,"# * Email         : liuxp731@qq.com")
   call append(4,"# * Create time   : ".strftime("%Y-%m-%d %H:%M"))
   call append(5,"# * Filename      : ".expand("%:t"))
   call append(6,"# * Description   : ")
   call append(7,"# **********************************************************")
endfunction

autocmd BufNewFile *.sh call AddTitleForShell()



"===
"===Sync my plugins setting
"===
if empty(glob('~/.vim/autoload/plug.vim'))
  silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
    \ https://raw.githubusercontent.com/lxp731/topazleaves/refs/heads/main/src/mdbook-files/plug.vim
  autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
endif



"===
"===System Setting
"===
let mapleader=" "
set nocompatible
set showcmd
set mouse=a
set clipboard=unnamed
vnoremap Y :w !xclip -i -sel c<CR>
filetype on
filetype indent on
filetype plugin on
filetype plugin indent on
"set laststatus=2
set autochdir
set dictionary+=/usr/share/dict/words
"autocmd InsertLeave * write
"autocmd FocusLost * if &modified | write | endif



"===
"===Open the vimrc anytime
"===
noremap <LEADER>rc :e ~/.vimrc<CR>
map <LEADER>fd /\(\<\w\+\>\)\_s*\1



"===
"===Show command autocomplete
"===
set wildignore=log/**,node_modules/**,target/**,tmp/**,*.rbc
set wildmenu
set wildmode=longest,list,full



"===
"===Search Setting
"===
set hlsearch
exec "nohlsearch"
set incsearch
set ignorecase
set smartcase



"===
"===Code Display
"===
set encoding=UTF-8
syntax on
set number
set relativenumber
set cursorline
let &t_ut=''



"===
"===Tab behavior
"===
set expandtab
set tabstop=2
set shiftwidth=2
set softtabstop=2
set list
set listchars=tab:▸\ ,trail:▫
set scrolloff=5



"===
"===Prevent auto line split
"===
set tw=0
set wrap
set indentexpr=
set backspace=indent,eol,start
set foldmethod=indent
set foldlevel=99



"===
"===快捷键映射
"===
nnoremap <LEADER><CR> :nohlsearch<CR>
nnoremap s <nop>
nnoremap S :w<CR>
nnoremap R :source $MYVIMRC<CR>
nnoremap XX :q!<CR>
nnoremap j k
nnoremap k j
nnoremap = nzz
nnoremap - Nzz
nnoremap W 5w
nnoremap B 5b
nnoremap <C-j> :belowright term<CR>



"===
"===Edit mode shortkey
"===
inoremap <C-z> <C-o>u
inoremap <C-l> <C-o>o
inoremap <C-S-k> <Esc>ddi
inoremap <C-y> <Esc>:normal! yyp<CR>a
inoremap <C-s> <Esc>:w<CR>i


"===
"===Line Moving
"===
nnoremap <A-Down> ddp
nnoremap <A-Up> dd2kp
inoremap <A-Up> <Esc>ddkPgi
inoremap <A-Down> <Esc>ddjPgi



"===
"===Words spell Checking
"===
map <LEADER>pl :set spell!<CR>
nnoremap <C-x> ea<C-x>s
inoremap <C-x> <Esc>ea<C-x>s



"===
"===分割窗口
"===
nnoremap sl :set splitright<CR>:vsplit<CR>
nnoremap snl :set nosplitright<CR>:vsplit<CR>
nnoremap sk :set splitbelow<CR>:split<CR>
nnoremap snk :set nosplitbelow<CR>:split<CR>
nnoremap <LEADER>l <C-w>l
nnoremap <LEADER>h <C-w>h
nnoremap <LEADER>j <C-w>k
nnoremap <LEADER>k <C-w>j
nnoremap <C-Up> :res +2<CR>
nnoremap <C-Down> :res -2<CR>
nnoremap <C-Left> :vertical resize-2<CR>
nnoremap <C-Right> :vertical resize+2<CR>
map <LEADER>sv <C-w>t<C-w>H
map <LEADER>sh <C-w>t<C-w>K



"===
"===Tab Management
"===
nnoremap th :tabprevious<CR>
nnoremap tl :tabnext<CR>
nnoremap to :tabclose<CR>
nnoremap tq :tabfirst<CR>
nnoremap tp :tablast<CR>
" Insert mode mappings
"inoremap tl <C-O>:tabnext<CR>
"inoremap th <C-O>:tabprevious<CR>
"inoremap tq <C-O>:tabfirst<CR>
"inoremap tp <C-O>:tablast<CR>



"===
"===保存VIM光标位置
"===
augroup remember_last_cursor_position
    autocmd!
    autocmd BufWritePost * mkview
    autocmd BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal g`\"" | endif
augroup END



"===
"===VIM 插件管理器
"===
call plug#begin('~/.vim/plugged')
Plug 'sheerun/vim-polyglot'
Plug 'connorholyday/vim-snazzy'

" File navigation
Plug 'preservim/nerdtree'
Plug 'Xuyuanp/nerdtree-git-plugin'

" Taglist
Plug 'preservim/tagbar'

" Error checking
Plug 'dense-analysis/ale'

" Auto Complete
Plug 'Valloric/YouCompleteMe'

" Undo Tree
Plug 'mbbill/undotree'

" Other visual enhancement
Plug 'nathanaelkane/vim-indent-guides'
Plug 'itchyny/vim-cursorword'

" Git
Plug 'rhysd/conflict-marker.vim'
Plug 'tpope/vim-fugitive'
Plug 'mhinz/vim-signify'
Plug 'gisphm/vim-gitignore', { 'for': ['gitignore', 'vim-plug'] }

" HTML, CSS, JavaScript, PHP, JSON, etc.
Plug 'elzr/vim-json'
Plug 'hail2u/vim-css3-syntax'
Plug 'spf13/PIV', { 'for' :['php', 'vim-plug'] }
Plug 'gko/vim-coloresque', { 'for': ['vim-plug', 'php', 'html', 'javascript', 'css', 'less'] }
Plug 'pangloss/vim-javascript', { 'for' :['javascript', 'vim-plug'] }
Plug 'mattn/emmet-vim'

" Python
Plug 'vim-scripts/indentpython.vim'
Plug 'linux-cultist/venv-selector.nvim'

" Markdown
Plug 'iamcco/markdown-preview.nvim', { 'do': { -> mkdp#util#install_sync() }, 'for' :['markdown', 'vim-plug'] }
Plug 'dhruvasagar/vim-table-mode', { 'on': 'TableModeToggle' }
Plug 'vimwiki/vimwiki'

" Bookmarks
Plug 'kshenoy/vim-signature'

" Other useful utilities
Plug 'terryma/vim-multiple-cursors'
Plug 'junegunn/goyo.vim' " distraction free writing mode
Plug 'tpope/vim-surround' " type ysks' to wrap the word with '' or type cs'` to change 'word' to `word`
Plug 'godlygeek/tabular' " type ;Tabularize /= to align the =
Plug 'gcmt/wildfire.vim' " in Visual mode, type i' to select all text in '', or type i) i] i} ip
Plug 'scrooloose/nerdcommenter' " in <space>cc to comment a line

" Dependencies
Plug 'MarcWeber/vim-addon-mw-utils'
Plug 'kana/vim-textobj-user'
Plug 'fadein/vim-FIGlet'

" commenter
Plug 'preservim/nerdcommenter'
call plug#end()



"===
"===Snazzy Setting
"===
map <LEADER>c1 :set background=dark<CR>:colorscheme snazzy<CR>:AirlineTheme drak<CR>
map <LEADER>c2 :set background=light<CR>:colorscheme sorbet<CR>:AirlineTheme dark<CR>
let g:SnazzyTransparent = 1
color sorbet
"color snazzy
"color slate
"color desert
"color industry
"color evening
"color habamax
"color peachpuff
"color elflord
"color pablo
"color murphy
"color lunaperche
"color koehler


"===
"===NERDTree Setting
"===
"Start NERDTree when Vim starts with a directory argument.
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists('s:std_in') |
    \ execute 'NERDTree' argv()[0] | wincmd p | enew | execute 'cd '.argv()[0] | endif
"Close the tab if NERDTree is the only window remaining in it.
autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif
nnoremap <C-t> :NERDTreeToggle<CR>
"nnoremap <C-n> :NERDTree<CR>
"nnoremap <C-f> :NERDTreeFind<CR>
"nnoremap <leader>n :NERDTreeFocus<CR>



" ===
" === NERDTree-git
" ===
"let g:NERDTreeGitStatusUseNerdFonts = 1
let g:NERDTreeGitStatusIndicatorMapCustom = {
                \ 'Modified'  :'✹',
                \ 'Staged'    :'✚',
                \ 'Untracked' :'✭',
                \ 'Renamed'   :'➜',
                \ 'Unmerged'  :'═',
                \ 'Deleted'   :'✖',
                \ 'Dirty'     :'✗',
                \ 'Ignored'   :'☒',
                \ 'Clean'     :'✔︎',
                \ 'Unknown'   :'?',
                \ }



" ===
" === Tagbar
" ===
" nmap <F8> :TagbarToggle<CR>



"===
"===ALE
"===
" let g:ale_fixers = {
" \   '*': ['remove_trailing_lines', 'trim_whitespace'],
" \   'javascript': ['eslint'],
" \}
" let g:ale_fix_on_save = 1
" call deoplete#custom#option('sources', {
" \ '_': ['ale', 'foobar'],
" \})
" let g:ale_completion_enabled = 1



"===
"===Markdown Preview
"===
let g:mkdp_auto_start = 0
let g:mkdp_auto_close = 1
let g:mkdp_refresh_slow = 0
let g:mkdp_command_for_global = 0
let g:mkdp_open_to_the_world = 0
let g:mkdp_open_ip = ''
let g:mkdp_browser = ''
let g:mkdp_echo_preview_url = 0
let g:mkdp_browserfunc = ''
let g:mkdp_preview_options = {
    \ 'mkit': {},
    \ 'katex': {},
    \ 'uml': {},
    \ 'maid': {},
    \ 'disable_sync_scroll': 0,
    \ 'sync_scroll_type': 'middle',
    \ 'hide_yaml_meta': 1
    \ }
let g:mkdp_markdown_css = ''
let g:mkdp_highlight_css = ''
let g:mkdp_page_title = '「${name}」'
let g:mkdp_port = '3001'
let g:mkdp_theme = 'light' "dark OR light
" combine preview window
" ensure to set let g:mkdp_auto_close = 0 if you have enable this option
let g:mkdp_combine_preview = 0
" auto refetch combine preview contents when change markdown buffer
" only when g:mkdp_combine_preview is 1
let g:mkdp_combine_preview_auto_refresh = 1
noremap mp :MarkdownPreview<CR>
noremap ms :MarkdownPreviewStop<CR>



"===
"===MarkdownEdit
"===
autocmd Filetype markdown inoremap ,1 #<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,2 ##<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,3 ###<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,4 ####<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,5 #####<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,6 ######<Space><Enter><++><Esc>kA
autocmd Filetype markdown inoremap ,f <Esc>/<++><CR>:nohlsearch<CR>c4l
autocmd Filetype markdown inoremap ,b **** <++><Esc>F*hi
autocmd Filetype markdown inoremap ,i ** <++><Esc>F*i
autocmd Filetype markdown inoremap ,s ~~~~ <++><Esc>F~hi
autocmd Filetype markdown inoremap ,d `` <++><Esc>F`i
autocmd Filetype markdown inoremap ,c ```<Enter><++><Enter>```<Enter><Enter><++><Esc>4kA
autocmd Filetype markdown inoremap ,a [](<++>) <++><Esc>F[a
autocmd Filetype markdown inoremap ,p ![](<++>) <++><Esc>F[a

function! CreateTable(num_cols)
  let col_str = repeat('|<++>', a:num_cols) . '|'
  let separator = repeat('|:----:', a:num_cols) . '|'
  let result = col_str . "\n" . separator . "\n" . col_str
  return result
endfunction

autocmd Filetype markdown inoremap ,t2 <Esc>i<C-R>=CreateTable(2)<CR><Esc>^3klc5l
autocmd Filetype markdown inoremap ,t3 <Esc>i<C-R>=CreateTable(3)<CR><Esc>^3klc5l
autocmd Filetype markdown inoremap ,t4 <Esc>i<C-R>=CreateTable(4)<CR><Esc>^3klc5l
autocmd Filetype markdown inoremap ,t5 <Esc>i<C-R>=CreateTable(5)<CR><Esc>^3klc5l
autocmd Filetype markdown inoremap ,t6 <Esc>i<C-R>=CreateTable(6)<CR><Esc>^3klc5l

" autocmd Filetype markdown inoremap ,t3 \|<++>\|<++>\|<++>\|<Enter>\|:----:\|:----:\|:----:\|<Enter>\|<++>\|<++>\|<++>\|<Enter><Esc>3klc4l
" autocmd Filetype markdown inoremap ,t2 \|<++>\|<++>\|<Enter>\|:----:\|:----:\|<Enter>\|<++>\|<++>\|<Enter><Esc>3klc4l

function! CreateMarkdownRow(num_cols)
  let col_str = repeat('|<++>', a:num_cols) . '|'
  return col_str
endfunction

autocmd Filetype markdown inoremap ,l2 <Esc>o<C-R>=CreateMarkdownRow(2)<CR><Esc>^lc5l
autocmd Filetype markdown inoremap ,l3 <Esc>o<C-R>=CreateMarkdownRow(3)<CR><Esc>^lc5l
autocmd Filetype markdown inoremap ,l4 <Esc>o<C-R>=CreateMarkdownRow(4)<CR><Esc>^lc5l
autocmd Filetype markdown inoremap ,l5 <Esc>o<C-R>=CreateMarkdownRow(5)<CR><Esc>^lc5l
autocmd Filetype markdown inoremap ,l6 <Esc>o<C-R>=CreateMarkdownRow(6)<CR><Esc>^lc5l

" autocmd Filetype markdown inoremap ,l2 \|<++>\|<++>\|
" autocmd Filetype markdown inoremap ,l3 \|<++>\|<++>\|<++>\|

autocmd Filetype markdown inoremap <C-s> <C-o>:w<CR>




"===
"===UndoTree
"===
nnoremap <F5> :UndotreeToggle<CR>



"===
"===vim-surround
"===
" objects: word(iw), line(s), tag(t)
" opretion: add, remove, change
" add: ys[objects] [Mark]
" remove: ds [Mark]
" change: cs [src_Mark], [dst_Mark]



"===
"===nerdcommenter
"===
let g:NERDCreateDefaultMappings = 1
let g:NERDSpaceDelims = 1
let g:NERDCompactSexyComs = 1
let g:NERDDefaultAlign = 'left'
let g:NERDAltDelims_java = 1
let g:NERDCustomDelimiters = { 'c': { 'left': '/**','right': '*/' } }
let g:NERDCommentEmptyLines = 1
let g:NERDTrimTrailingWhitespace = 1
let g:NERDToggleCheckAllLines = 1

NERDTree

Ref: https://vimawesome.com/plugin/nerdtree-red

Install NERDTree

Add Plug 'preservim/nerdtree' to your .vimrc, For example:

Plug 'preservim/nerdtree'

Reopen a Vim window and type :PlugInstall to install NERDTree.

Setting Shortcut Keys

Edit .vimrc and add the following code:

nnoremap <leader>n :NERDTreeFocus<CR>
nnoremap <C-n> :NERDTree<CR>
nnoremap <C-t> :NERDTreeToggle<CR>
nnoremap <C-f> :NERDTreeFind<CR>
  • <leader>n: Default <leader> is \. Change the foucus from file to NERDTree.
  • <C-n>: Open NERDTree.
  • <C-t>: Open or Close NERDTree.
  • <C-f>: Open / in NERDTree.

Auto-Open NERDTree when Vim starts with a directory argument

Add the following code to your .vimrc:

" Start NERDTree when Vim starts with a directory argument.
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists('s:std_in') |
    \ execute 'NERDTree' argv()[0] | wincmd p | enew | execute 'cd '.argv()[0] | endif

"Close the tab if NERDTree is the only window remaining in it.
autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif

More details at VimAwesome or NERDTree.

Rendering

Rendering

NerdTree-Git

Github Repo

https://github.com/Xuyuanp/nerdtree-git-plugin

Install

Plug 'Xuyuanp/nerdtree-git-plugin'
let g:NERDTreeGitStatusShowCounts = 1
let g:NERDTreeGitStatusIndicatorMapCustom = {
                \ 'Modified'  :'✹',
                \ 'Staged'    :'✚',
                \ 'Untracked' :'✭',
                \ 'Renamed'   :'➜',
                \ 'Unmerged'  :'═',
                \ 'Deleted'   :'✖',
                \ 'Dirty'     :'✗',
                \ 'Ignored'   :'☒',
                \ 'Clean'     :'✔︎',
                \ 'Unknown'   :'?',
                \ }

Install Nerd Fonts

https://raw.githubusercontent.com/mcarvalho1/Simple-NerdFonts-Downloader/c7854dae2153aa199277926bed4b992488b65a3d/nf_downloader.sh

Rendering

Rendering

YouCompleteMe

Github Repo

https://github.com/ycm-core/YouCompleteMe

https://vimawesome.com/plugin/youcompleteme

Installation

Plug 'Valloric/YouCompleteMe'

After :PlugInstall, if you use vim-plug

cd ~/.vim/plugged/YouCompleteMe
python3 install.py

If failed, according to tips, install cmake or cmake3.

Slove GLIBCXX_3.4.32 not found

sudo apt update
sudo apt install libstdc++6
strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX

Generally, you can find GLIBCXX_3.4.32 in your system. Next, just copy libstdc++.so.6* to default path that in error log.

sudo cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6* /home/knight/miniconda3/lib/

Rendering

https://camo.githubusercontent.com/ff645d6ac63801b82adf04c354be7edfce79c60f38889f441b351dd8fe27372b/68747470733a2f2f692e696d6775722e636f6d2f304f50346f6f642e676966

Vim Support System Clipboard

Check Vim version

vim --version | grep clipboard

Output:

knight@Lenovo:~$ vim --version | grep "clipboard"
-clipboard         +keymap            +printer           +vertsplit
+ex_extra          +mouse_netterm     +syntax            -xterm_clipboard

-clipboard -xterm_clipboard means that vim not support system clipboard.

Remove vim

Uninstall vim if you have installed.

sudo apt remove vim && sudo apt autoremove

Install vim-gtk3

sudo apt install vim-gtk3

Check Vim version again

vim --version | grep clipboard

Output:

knight@Lenovo:~$ vim --version | grep clipboard
+clipboard         +keymap            +printer           +vertsplit
+ex_extra          +mouse_netterm     +syntax            +xterm_clipboard

Confirem the key value is +clipboard or +xterm_clipboard.

Edit .vimrc

set clipboard=unnamedplus

The last you can use "*y to copy the text to system clipboard.


Use Xclip

sudo apt install xclip

Modify .vimrc

vnoremap Y :w !xclip -i -sel c<CR>

Then you can select some contents in visual mode, and press Y. Finally, you can use <Ctrl-v> to paste it anywhere.

FZF

Official Website

Install

# Clone the fzf repository
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf

# Run the install script
~/.fzf/install

Setting .bashrc

A basic example, to show how to link progress with fzf.

# add a alias to change git branch
alias gcb="git branch | fzf --preview 'git show --color=always {-1}' \
                 --bind 'enter:become(git checkout {-1})' \
                 --height 60% --layout reverse"

Then, setting ENV vars of fzf, unlock advanced function.

# fzf init
eval "$(~/.fzf/bin/fzf --bash)"
[ -f ~/.fzf.bash ] && source ~/.fzf.bash

Default fzf self build-in Ctrl+R to display history cmd, Ctrl+T to show files and dirs of local path, Alt+C to exec cd cmd. Well, you can rewrite these function.

# CTRL-Y to copy the command into clipboard using pbcopy
export FZF_CTRL_R_OPTS="
  --bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort'
  --color header:italic
  --header 'Press CTRL-Y to copy command into clipboard'
  --height 80% --layout reverse"

# Preview file content using bat (https://github.com/sharkdp/bat)
export FZF_CTRL_T_OPTS="
  --walker-skip .git,node_modules,target
  --preview 'batcat -n --color=always {}'
  --bind 'ctrl-/:change-preview-window(down|hidden|)'
  --height 80% --layout reverse"

# Print tree structure in the preview window
export FZF_ALT_C_OPTS="
  --walker-skip .git,node_modules,target
  --preview 'tree -C {}'
  --height 80% --layout reverse"

# ripgrep->fzf->vim [QUERY]
# sudo apt install -y ripgrep
rfv() (
  RELOAD='reload:rg --column --color=always --smart-case {q} || :'
  OPENER='if [[ $FZF_SELECT_COUNT -eq 0 ]]; then
            vim {1} +{2}     # No selection. Open the current line in Vim.
          else
            vim +cw -q {+f}  # Build quickfix list for the selected items.
          fi'
  fzf --disabled --ansi --multi \
      --bind "start:$RELOAD" --bind "change:$RELOAD" \
      --bind "enter:become:$OPENER" \
      --bind "ctrl-o:execute:$OPENER" \
      --bind 'alt-a:select-all,alt-d:deselect-all,ctrl-/:toggle-preview' \
      --delimiter : \
      --preview 'batcat --style=full --color=always --highlight-line {2} {1}' \
      --preview-window '~4,+{2}+4/3,<80(up)' \
      --query "$*"
)

In fzf model, you can press Esc to quit fzf model.

FZF Replace Bash Completion

Github Repo

https://github.com/lincheney/fzf-tab-completion

Install Script

mkdir -p ~/.fzf/shell && \
wget -O ~/.fzf/shell/fzf-bash-completion.sh \
    https://raw.githubusercontent.com/lincheney/fzf-tab-completion/refs/heads/master/bash/fzf-bash-completion.sh

Modify .bashrc

cat >> ~/.bashrc << EOF
# use fzf replace system completion
source ~/.fzf/shell/fzf-bash-completion.sh
bind -x '"\t": fzf_bash_completion'
EOF
source ~/.bashrc

FZF Integrate Git

Github Repo

https://github.com/junegunn/fzf-git.sh

Install

mkdir -p ~/.fzf/shell && \
cd ~/.fzf/shell && \
wget https://raw.githubusercontent.com/junegunn/fzf-git.sh/refs/heads/main/fzf-git.sh

Modify .bashrc

cat >> ~/.bashrc << EOF
# fzf integrade git
source ~/.fzf/shell/fzf-git.sh
EOF
source ~/.bashrc

All Kinds of Proxy Setting

In china, you can't access to the real Internet directly. So you have to use some proxy in some software.

Configure System Proxy

Edit a Script

sudo vim  /etc/profile.d/proxy.sh
# set proxy config via profie.d - should apply for all users
export http_proxy="http://10.10.1.10:8080/"
export https_proxy="http://10.10.1.10:8080/"
export ftp_proxy="http://10.10.1.10:8080/"
export no_proxy="127.0.0.1,localhost"
# For curl
export HTTP_PROXY="http://10.10.1.10:8080/"
export HTTPS_PROXY="http://10.10.1.10:8080/"
export FTP_PROXY="http://10.10.1.10:8080/"
export NO_PROXY="127.0.0.1,localhost"

Add Exec Permission

sudo chmod +x  /etc/profile.d/proxy.sh

Apply Setting

source /etc/profile.d/proxy.sh

Confirm ENV

env | grep -i proxy

Configure Docker Proxy

Edit Conf File

sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf

Add Lines

[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"

Reload Daemon & Restart Docker

sudo systemctl daemon-reload
sudo systemctl restart docker

Configure Container Proxy

vim ~/.docker/config.json

{ 
  "proxies":
    { 
      "default": 
        { 
          "httpProxy": "http://172.17.0.1:7890", 
          "httpsProxy": "https://172.17.0.1:7890", 
          "noProxy": "*.<domain>,127.0.0.0/8" 
        } 
    } 
}

Configure K3S Proxy

  • /etc/systemd/system/k3s.service.env

  • /etc/systemd/system/k3s-agent.service.env

HTTP_PROXY=http://your-proxy.example.com:8888
HTTPS_PROXY=http://your-proxy.example.com:8888
NO_PROXY=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

Useful Scripts

In Linux, you can use some scripts to do some repetitive tasks.

Switch Node Version

sudo vim hexo_start_stop.sh
sudo chmod +x hexo_start_stop.sh
#!/bin/bash

# 检查参数
if [ "$#" -ne 1 ]; then
    echo "Usage: $0 start|stop"
    exit 1
fi

# 定义变量
NODE_V12_DIR="/home/knight/node/node-v12/bin"
NODE_V20_DIR="/home/knight/node/node-v20/bin"
NODE_BIN="/usr/bin/node"
NODE_LOCAL_BIN="/usr/local/bin/node"
NPM_BIN="/usr/bin/npm"
NPM_LOCAL_BIN="/usr/local/bin/npm"
NPX_BIN="/usr/bin/npx"
NPX_LOCAL_BIN="/usr/local/bin/npx"
# HEXO_LOCAL_BIN="/usr/local/bin/hexo"

# 根据参数执行相应的操作
case "$1" in
    start)
        # 更新符号链接到 Node v12
        sudo ln -sf "$NODE_V12_DIR/node" "$NODE_BIN"
        sudo ln -sf "$NODE_V12_DIR/node" "$NODE_LOCAL_BIN"
        sudo ln -sf "$NODE_V12_DIR/npm" "$NPM_BIN"
        sudo ln -sf "$NODE_V12_DIR/npm" "$NPM_LOCAL_BIN"
        sudo ln -sf "$NODE_V12_DIR/npx" "$NPX_BIN"
        sudo ln -sf "$NODE_V12_DIR/npx" "$NPX_LOCAL_BIN"
        # sudo ln -sf "$NODE_V12_DIR/hexo" "$HEXO_LOCAL_BIN"
        echo "Node, NPM, and NPX links updated to Node v12."
        ;;
    stop)
        # 更新符号链接到 Node v20
        sudo ln -sf "$NODE_V20_DIR/node" "$NODE_BIN"
        sudo ln -sf "$NODE_V20_DIR/node" "$NODE_LOCAL_BIN"
        sudo ln -sf "$NODE_V20_DIR/npm" "$NPM_BIN"
        sudo ln -sf "$NODE_V20_DIR/npm" "$NPM_LOCAL_BIN"
        sudo ln -sf "$NODE_V20_DIR/npx" "$NPX_BIN"
        sudo ln -sf "$NODE_V20_DIR/npx" "$NPX_LOCAL_BIN"
        # sudo rm -rf "$HEXO_LOCAL_BIN"
        echo "Node, NPM, and NPX links updated to Node v20."
        ;;
    *)
        echo "Invalid argument. Usage: $0 start|stop"
        exit 1
        ;;
esac

exit 0

Control Docker Proxy Up/Down

sudo vim docker_proxy_start_stop.sh
sudo chmod +x docker_proxy_start_stop.sh
#!/bin/bash

# Define paths
CONF_FILE="/etc/systemd/system/docker.service.d/http-proxy.conf"
BACKUP_CONF_FILE="/etc/systemd/system/docker.service.d/http-proxy.conf.bak"

# Function to enable proxy
enable_proxy() {
    # Check if the current configuration file is already the backup
    if [ -f "$CONF_FILE" ] && cmp --silent "$CONF_FILE" "$BACKUP_CONF_FILE"; then
        echo "Proxy configuration is already enabled."
    else
        # Move the backup configuration to the active configuration file
        sudo mv "$BACKUP_CONF_FILE" "$CONF_FILE"
        
        # Reload systemd manager configuration
        sudo systemctl daemon-reload
        
        # Restart Docker service
        sudo systemctl restart docker.service
        echo "Proxy configuration enabled."
    fi
}

# Function to disable proxy
disable_proxy() {
    # Check if the current configuration file is the original
    if [ -f "$CONF_FILE" ] && ! cmp --silent "$CONF_FILE" "$BACKUP_CONF_FILE"; then
        # Move the active configuration file to the backup
        sudo mv "$CONF_FILE" "$BACKUP_CONF_FILE"
        
        # Reload systemd manager configuration
        sudo systemctl daemon-reload
        
        # Restart Docker service
        sudo systemctl restart docker.service
        echo "Proxy configuration disabled."
    else
        echo "Proxy configuration is already disabled."
    fi
}

# Check the command argument
case $1 in
    start)
        enable_proxy
        ;;
    stop)
        disable_proxy
        ;;
    *)
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac

exit 0

Push Docker Images to Private Registry

Tips:When install images, you need open the proxy, but you must close it before push.

Extract Images Name to File

From the Helm's values.yaml, extract the images name and tag to images.tmp.

Usage:get_images.sh values-nginx.yaml

#!/bin/bash
# **********************************************************
# * Author        : Burgess Leo
# * Email         : liuxp731@qq.com
# * Create time   : 2024-09-13 16:06
# * Filename      : get_images.sh
# * Description   : Extracts Docker image names and tags from a YAML file and writes them to images.tmp
# **********************************************************

# 检查是否传入文件名作为参数
if [ "$#" -ne 1 ]; then
  echo "用法: $0 <values-nginx.yaml>"
  exit 1
fi

# 从命令行参数获取文件名
input_file="$1"

# 清空或创建 images.tmp 文件
> images.tmp

while read -r line; do
  if [[ $line == *"repository:"* ]]; then
    repository=$(echo $line | cut -d':' -f2 | xargs)
  elif [[ $line == *"tag:"* ]]; then
    tag=$(echo $line | cut -d':' -f2 | xargs)
    # 将结果写入 images.tmp 文件
    echo "$repository:$tag" >> images.tmp
  fi
done < "$input_file"

Pull Docker Images

Install all dcoker images in images.tmp file, one by one. If you have else docker images_list file, you can use it instead, just confirm every lines only has one docker image name.

Usage:pull_images.sh images.tmp

#!/bin/bash
# **********************************************************
# * Author        : Burgess Leo
# * Email         : liuxp731@qq.com
# * Create time   : 2024-09-13 16:34
# * Filename      : pull_images.sh
# * Description   : Pull images from Internet
# **********************************************************

# 检查是否传入文件名作为参数
if [ "$#" -ne 1 ]; then
  echo "用法: $0 <images.tmp>"
  exit 1
fi

# 从命令行参数获取文件名
input_file="$1"

# 读取文件并拉取每个镜像
while read -r image; do
  if [ -n "$image" ]; then
    echo "正在拉取镜像: $image"
    docker pull "$image"
  fi
done < "$input_file"

Rename Docker Images

The modified image names will be saved in the new_images.tmp file. And you can modify the private_registry to change the registry you want to push to.

Usage:update_images.sh images.tmp

#!/bin/bash
# **********************************************************
# * Author        : Burgess Leo
# * Email         : liuxp731@qq.com
# * Create time   : 2024-09-13 16:06
# * Filename      : update_and_tag_images.sh
# * Description   : Updates image paths and tags Docker images based on a specified file
# **********************************************************

# 检查是否传入文件名作为参数
if [ "$#" -ne 1 ]; then
  echo "用法: $0 <images.tmp>"
  exit 1
fi

# 从命令行参数获取文件名
input_file="$1"
output_file="new_images.tmp"
private_registry="192.167.3.18/"

# 创建或清空输出文件
> "$output_file"

# 处理文件内容并执行 docker tag 命令
while IFS= read -r original_image; do
  # 检查行是否为空
  if [[ -n "$original_image" ]]; then
    # 在镜像名称前加上私有仓库地址
    new_image_name="${private_registry}${original_image}"
    
    # 输出正在标记的镜像信息
    echo "正在标记镜像: docker tag $original_image $new_image_name"
    
    # 执行 docker tag 命令
    docker tag "$original_image" "$new_image_name"
    
    # 将新的镜像名称写入输出文件
    echo "$new_image_name" >> "$output_file"
  fi
done < "$input_file"

echo "所有镜像已成功标记并保存到 $output_file"

After Tag docker images, you must check the new_images_name.tmp, ensure the image names are correct. And you must confirm about projects created in your private harbor.

Push Images

Push images to a remote registry. This script reads a list of image names from a file named "new_images.tmp", and pushes them to a remote registry.

Usage:push_images.sh new_images.tmp

#!/bin/bash
# **********************************************************
# * Author        : Burgess Leo
# * Email         : liuxp731@qq.com
# * Create time   : 2024-09-14 09:01
# * Filename      : push_images.sh
# * Description   : Push Docker images to a registry
# **********************************************************

# 检查是否传入文件名作为参数
if [ "$#" -ne 1 ]; then
  echo "用法: $0 <images.tmp>"
  exit 1
fi

# 从命令行参数获取文件名
images_file="$1"
target_registry="192.167.3.18/library/"

# 遍历images.tmp文件中的每一行
while IFS= read -r line; do
    # 检查行是否为空
    if [ -z "$line" ]; then
        continue
    fi

    # 打印操作信息
    echo "正在推送镜像: $line"

    # 推送镜像
    docker push "$line"

done < "$images_file"

echo "所有指定的镜像已被推送。"

Delete Images from Local

Delete images from local.

Usage:delete_images.sh new_images.tmp

#!/bin/bash
# **********************************************************
# * Author        : Burgess Leo
# * Email         : liuxp731@qq.com
# * Create time   : 2024-09-14 09:02
# * Filename      : delete_images.sh
# * Description   : Delete images that pushed
# **********************************************************

# 检查是否有参数传递
if [ $# -ne 1 ]; then
    echo "Usage: $0 <path-to-file>"
    exit 1
fi

# 指定包含镜像名称的文件路径
images_file="$1"

# 检查文件是否存在
if [ ! -f "$images_file" ]; then
    echo "Error: File '$images_file' not found."
    exit 1
fi

# 逐行读取文件中的镜像名称
while IFS= read -r image; do
    # 删除镜像,忽略不存在的镜像
    if docker rmi "$image" &>/dev/null; then
        echo "Image $image has been deleted."
    else
        echo "Image $image does not exist or could not be deleted."
    fi
done < "$images_file"

echo "All listed images have been processed."

ALL IN ONE

Merge all the above scripts into one.

#!/bin/bash
# **********************************************************
# * Author        : Burgess Leo
# * Email         : liuxp731@qq.com
# * Create time   : 2024-09-13 16:06
# * Filename      : all_in_one.sh
# * Description   : Pull images
# **********************************************************

# 欢迎信息
echo "欢迎使用 Docker 镜像管理脚本!"
echo ""

# 菜单函数
print_menu() {
  echo "*********************************************************"
  echo "*                                                       *"
  echo "*     1. Get images from Helm yaml files.               *"
  echo "*                                                       *"
  echo "*     2. Pull images from docker hub to local.          *"
  echo "*                                                       *"
  echo "*     3. Docker tag images you need to change.          *"
  echo "*                                                       *"
  echo "*     4. Push images to your private docker registry.   *"
  echo "*                                                       *"
  echo "*     5. Delete images from local.                      *"
  echo "*                                                       *"
  echo "*     6. cat images.tmp.                                *"
  echo "*                                                       *"
  echo "*     7. cat new_images.tmp.                            *"
  echo "*                                                       *"
  echo "*     8. About.                                         *"
  echo "*                                                       *"
  echo "*     0. Exit.                                          *"
  echo "*                                                       *"
  echo "*********************************************************"
}

# 主循环
while true; do
  print_menu
  read -p "请输入功能数字: " choice

  case $choice in
    1)
      read -p "请输入 Helm yaml 文件路径: " yaml_file
      if [ ! -f "$yaml_file" ]; then
        echo "错误: 文件 '$yaml_file' 不存在."
      else
        > images.tmp
        while read -r line; do
          if [[ $line == *"repository:"* ]]; then
            repository=$(echo $line | cut -d':' -f2 | xargs)
          elif [[ $line == *"tag:"* ]]; then
            tag=$(echo $line | cut -d':' -f2 | xargs)
            echo "$repository:$tag" >> images.tmp
          fi
        done < "$yaml_file"
        echo "已从 '$yaml_file' 中提取镜像并保存到 'images.tmp',由于 Helm yaml 文件可能包含重复的镜像以及失效的 Tag 名称,请手动检查 images.tmp 文件。"
      fi

    ;;
    2)
      read -p "请输入 images.tmp 文件路径 (默认: images.tmp): " images_file
      images_file=${images_file:-images.tmp} # 设置默认值

      if [ ! -f "$images_file" ]; then
        echo "错误: 文件 '$images_file' 不存在."
      else
        while IFS= read -r image || [ -n "$image" ]; do # 修复读取逻辑以处理没有换行的情况
          if [ -n "$image" ]; then
            echo "正在拉取镜像: $image"
            docker pull "$image"
          fi
        done < "$images_file"
        echo "所有镜像已成功拉取."
      fi

    ;;
    3)
      read -p "请输入 images.tmp 文件路径 (默认: images.tmp): " images_file
      images_file=${images_file:-images.tmp} # 设置默认值

      if [ ! -f "$images_file" ]; then
        echo "错误: 文件 '$images_file' 不存在."
      else
        output_file="new_images.tmp"
        header="192.167.3.18/"
        > "$output_file"

        while IFS= read -r original_image || [ -n "$original_image" ]; do # 修复读取逻辑以处理没有换行的情况
          # 在每一行前添加私有镜像仓库地址
          new_image_name="${header}${original_image}"
          echo "正在标记镜像: docker tag $original_image $new_image_name"
          docker tag "$original_image" "$new_image_name"
          echo "$new_image_name" >> "$output_file"
        done < "$images_file"

        if [ -s "$output_file" ]; then # 检查输出文件是否非空
          echo "所有镜像已成功标记并保存到 '$output_file'."
        else
          echo "警告: '$output_file' 文件为空,未能标记任何镜像."
        fi
      fi

    ;;
    4)
      read -p "请输入 new_images.tmp 文件路径 (默认: new_images.tmp): " images_file
      images_file=${images_file:-new_images.tmp} # 设置默认值

      if [ ! -f "$images_file" ]; then
        echo "错误: 文件 '$images_file' 不存在."
      else
        while IFS= read -r line || [ -n "$line" ]; do # 修复读取逻辑以处理没有换行的情况
          if [ -z "$line" ]; then continue; fi
          echo "正在推送镜像: $line"
          docker push "$line"
        done < "$images_file"

        echo "所有指定的镜像已被推送."
      fi

    ;;
    5)
      read -p "请输入包含要删除的镜像名称的文件路径 (默认: new_images.tmp): " images_file
      images_file=${images_file:-new_images.tmp} # 设置默认值

      if [ ! -f "$images_file" ]; then
        echo "错误: 文件 '$images_file' 不存在."
      else
        while IFS= read -r image || [ -n "$image" ]; do # 修复读取逻辑以处理没有换行的情况
          if docker rmi "$image" &>/dev/null; then
            echo "镜像 $image 已被删除."
          else
            echo "镜像 $image 不存在或无法删除."
          fi
        done < "$images_file"

        echo "所有列出的镜像已被处理."
      fi

    ;;
    6)
      cat images.tmp
      
    ;;
    7)
      cat new_images.tmp
      
    ;;
    8)
      # 打印关于信息
      cat << 'EOF'
        _..._   666       
      .'     '.      _
     /    .-""-\   _/ \
   .-|   /:.   |  |   |
   |  \  |:.   /.-'-./ 
   | .-'-;:__.'    =/  
   .'=  *=|NASA _.='   
  /   _.  |    ;       
 ;-.-'|    \   |       
/   | \    _\  _\      
\__/'._;. \==' ==\     
         \    \   |    
         /    /   /    
         /-._/-._/     
  lxp    \   `\  \     
          `-._/._/     
EOF

    ;;
    0)
      echo "退出程序。再见!"
      exit 0

    ;;
    *)
      echo "无效的选择,请重新输入."
    ;;
  esac

  # 打印分隔行以提高可读性,并重新显示菜单
  printf "\n\n\n"

done

Funny Docker Projects

Collected some funny docker projects here. If you want to try, confirm you install docker and docker-compose first.

  • OpenWeb-UI

    You can chat with your local ollama models in browser. It's provide history management and session management.

  • YesplayMusic

    A music player with a beautiful UI. You can deploy it on your own server.

OpenWeb-UI

open-webui Official Website

https://docs.openwebui.com/

Docker Deployment

version: '3'

services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    ports:
      - "3000:8080"
    volumes:
      - open-webui:/app/backend/data
#    restart: always
    extra_hosts:
      - "host.docker.internal:host-gateway"

volumes:
  open-webui:

Docker deploy open-webui needs to configure ollama Service Discovery, or ollama can't discern local models.

Yesplaymusic

Official Website

https://github.com/qier222/YesPlayMusic

Docker Deployment

version: '3.9'

services:
  yesplaymusic:
    image: fogforest/yesplaymusic
    container_name: yesplaymusic
    restart: always
    ports:
      - "7900:80"

Arch linux Init

  1. Modify pacman mirror
sudo vim /etc/pacman.d/mirrorlist
## China
Server = https://mirrors.aliyun.com/archlinux/$repo/os/$arch
Server = http://mirrors.aliyun.com/archlinux/$repo/os/$arch
Server = https://mirrors.tuna.tsinghua.edu.cn/archlinux/$repo/os/$arch
Server = http://mirrors.tuna.tsinghua.edu.cn/archlinux/$repo/os/$arch
Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch
Server = http://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch
Server = https://mirrors.neusoft.edu.cn/archlinux/$repo/os/$arch
Server = http://mirrors.neusoft.edu.cn/archlinux/$repo/os/$arch
Server = http://mirrors.163.com/archlinux/$repo/os/$arch
Server = http://mirrors.bfsu.edu.cn/archlinux/$repo/os/$arch
Server = https://mirrors.bfsu.edu.cn/archlinux/$repo/os/$arch
sudo vim /etc/pacman.conf
[archlinuxcn]
SigLevel = Optional TrustedOnly
Server = https://mirrors.tuna.tsinghua.edu.cn/archlinuxcn/$arch
Server = https://mirrors.ustc.edu.cn/archlinuxcn/$arch
Server = https://mirrors.aliyun.com/archlinuxcn/$arch
sudo pacman -Syy
sudo pacman -S yay base-devel tree neofetch git
  1. Install firefox
sudo pacman -S firefox
  1. Install font
sudo pacman -S noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra ttf-dejavu ttf-liberation
  1. modify
sudo vim /etc/locale.gen
zh_CN.UTF-8 UTF-8
su
locale-gen && echo LANG=zh_CN.UTF-8 > /etc/locale.conf
exit
  1. google-pinyin
sudo pacman -S fcitx5-im 
sudo pacman -S fcitx5-chinese-addons
sudo pacman -S fcitx5-qt fctitx5-gtk fcitx5-lua
  1. modify
sudo vim /etc/environment
GTK_IM_MODULE=fcitx
QT_IM_MODULE=fcitx
XMODIFIERS=@im=fcitx
SDL_IM_MODULE=fcitx
GLFM_IM_MODULE=ibus

Keyboard Layout

Switch to colemak layout.

setxkbmap us -variant colemak

Colemak

Switch to QWERTY layout.

setxkbmap us; xset -r 66

Ref: https://colemak.com/Unix

Disable Hibernate When Close Laptop

Edit Conf File

sudo gedit /etc/systemd/logind.conf

Modify Line

HandleLidSwitch=ignore

Restart Service

sudo systemctl restart systemd-logind

kns Locking Namespace

Install fzf

  1. Source Code Install(Recommend)
# Clone the fzf repository
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf

# Run the install script
~/.fzf/install
  1. apt install
sudo apt install fzf

Edit kns Script

vim kns
#!/bin/sh
# quick Kubernetes Namespace Switcher
# ISC Blendle, 2017

set -eu

if [ ! -x "$(which kubectl 2>/dev/null)" ]; then
  echo "please install: kubectl (https://kubernetes.io/docs/tasks/kubectl/install/)" >&2
  exit 1
fi
if [ ! -x "$(which fzf 2>/dev/null)" ]; then
  echo "please install: fzf (https://github.com/junegunn/fzf)" >&2
  exit 1
fi

current="$(kubectl config current-context)"
namespace="$(kubectl config view -o jsonpath="{.contexts[?(@.name == '${current}')].context.namespace}")"
if [ -z "$namespace" ]; then
  namespace="default"
fi

selected=$( (kubectl get namespaces -o=jsonpath="{.items[?(@.metadata.name!='$namespace')].metadata.name}" | xargs -n 1; echo $namespace ) | fzf -0 -1 --tac -q "${1:-""}" --prompt "$current> ")
if [ -n "$selected" ]; then
  kubectl config set-context "$current" "--namespace=$selected" >/dev/null
  echo "Set context namespace to \"$selected\""
fi

Add Exec Permission

chmod +x kns
sudo mv kns /usr/local/bin/kns

Classic CI/CD Script

variables:
  $CI_REGISTRY: habor.dcits.auto
  $CI_REGISTRY_IMAGE: liuxp731/webui


stages:
  - test
  - build
  - deploy


run_test:
  stage: test
  image: python:3.9-slim-buster
  before_script:
    - apt-get update && apt-get install -y make
  script:
    - make test


build_image:
  stage: build
  image: docker:20.10.16
  services:
    - docker:20.10.16-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
   - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY  
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA


deploy:
  stage: deploy
  before_script:
    - chmod 400 $SSH_KEY
  script:
    - ssh -o StrictHostKeyChecking=no -i $SSH_KEY $SSH_USER@$SSH_HOST "
      docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY &&
      docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA &&
      docker ps -a | xargs docker stop | xargs docker rm &&
      docker run -dit -p 5000:5000 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
      "

Command

:w !sudo tee %
openssl x509 -noout -text -in ca.crt
openssl verify -CAfiile ca.pem client.pem
diff -eq < (openssl x509 -pubkey -noout -in cert.crt) < (openssl rsa -pubout -in cert.key)

VS-Code Control Remote Hosts

Configure

ssh-keygen -t rsa

ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.1

Add ssh config

vim ~/.ssh/config

# 添加以下内容
Host ali
  HostName 192.168.1.1
  User root
  IdentityFile ~/.ssh/id_rsa
  Port 22

Install VS-Code Plugin

点击VSCode左下角图标,形似“><”,点击会自动安装。

Ollama Service Discovery

Editing the systemd service file

sudo vim /etc/systemd/system/ollama.service

Add ENV under [Service] Item

[Service]
Environment="OLLAMA_HOST=0.0.0.0"

Reload and Restart

sudo systemctl daemon-reload
sudo systemctl restart ollama