SSH 命令的三种代理功能(-L/-R/-D)

ssh 命令除了登陆外还有三种代理功能:

  • 正向代理(-L):相当于 iptable 的 port forwarding
  • 反向代理(-R):相当于 frp 或者 ngrok
  • socks5 代理(-D):相当于 ss/ssr

如要长期高效的服务,应使用对应的专用软件。如没法安装软件,比如当你处在限制环境下想要访问下某个不可达到的目标,或者某个临时需求,那么 ssh 就是你的兜底方案。

正向代理:

所谓 “正向代理” 就是在本地启动端口,把本地端口数据转发到远端。

用法1:远程端口映射到其他机器

HostB 上启动一个 PortB 端口,映射到 HostC:PortC 上,在 HostB 上运行:

HostB$ ssh -L 0.0.0.0:PortB:HostC:PortC user@HostC

这时访问 HostB:PortB 相当于访问 HostC:PortC(和 iptable 的 port-forwarding 类似)。

用法2:本地端口通过跳板映射到其他机器

HostA 上启动一个 PortA 端口,通过 HostB 转发到 HostC:PortC上,在 HostA 上运行:

HostA$ ssh -L 0.0.0.0:PortA:HostC:PortC  user@HostB

这时访问 HostA:PortA 相当于访问 HostC:PortC。

两种用法的区别是,第一种用法本地到跳板机 HostB 的数据是明文的,而第二种用法一般本地就是 HostA,访问本地的 PortA,数据被 ssh 加密传输给 HostB 又转发给 HostC:PortC。

反向代理:

所谓“反向代理”就是让远端启动端口,把远端端口数据转发到本地。

HostA 将自己可以访问的 HostB:PortB 暴露给外网服务器 HostC:PortC,在 HostA 上运行:

HostA$ ssh -R HostC:PortC:HostB:PortB  user@HostC

那么链接 HostC:PortC 就相当于链接 HostB:PortB。使用时需修改 HostC 的 /etc/ssh/sshd_config,添加:

GatewayPorts yes

相当于内网穿透,比如 HostA 和 HostB 是同一个内网下的两台可以互相访问的机器,HostC是外网跳板机,HostC不能访问 HostA,但是 HostA 可以访问 HostC。

Continue reading

Loading

Posted in 未分类 | Tagged | Leave a comment

别让 cd 浪费你的时间

终端下工作最烦躁的就是路径切换,没有自动路径切换的帮助,就像在泥里走路,于是有了各种 autojump / z / fasd 等工具来提升路径切换的效率,今天向大家介绍一个更好用的工具:z.lua,用熟练了以后就像终端里溜冰,路劲切换从此指哪打哪。

z.lua 是一个会学习你使用习惯的 cd 命令,它会跟踪你在 shell 下访问过的路径,通过一套称为 Frecent 的机制(源自 Mozilla),经过一段简短的学习之后,z.lua 会帮你跳转到所有匹配正则关键字的路径里 Frecent 值最高的那条路径去。

正则将按顺序进行匹配,”z foo bar” 可以匹配到 /foo/bar ,但是不能匹配 /bar/foo。

特性说明:

  • 性能比 z.sh 快三倍,比 fasd / autojump 快十倍以上。
  • 支持 Posix Shell:bash, zsh, dash, sh, ash, busybox 等等。
  • 支持 Fish Shell,Power Shell 和 Windows cmd。
  • 使用增强匹配算法,更准确的带你去到你想去的地方。
  • 低占用,能够仅在当前路径改变时才更新数据库(将 $_ZL_ADD_ONCE 设成 1)。
  • 交互选择模式,如果有多个匹配结果的话,跳转前允许你进行选择。
  • 交互选择模式,支持使用 fzf 进行可视化结果筛选(可选)。
  • 快速跳转到父目录,或者项目根目录,代替反复 “cd ../../..” 。
  • 为不同的操作系统,不同的 Shell 程序提供统一的使用体验。
  • 兼容 lua 5.1, 5.2 和 5.3 以上版本。
  • 自包含且无额外依赖,单个 z.lua 文件完成所有工作。

软件安装:

将下面对应语句添加到你的 .bashrc / .zshrc / .profile 或者对应 shell 的初始化脚本末尾:

eval "$(lua /path/to/z.lua --init bash enhanced once echo)"    # BASH 初始化
eval "$(lua /path/to/z.lua --init zsh enhanced once echo)"     # ZSH 初始化
eval "$(lua /path/to/z.lua --init posix enhanced once echo)"   # 其他 Posix Shell 初始化
source (lua /path/to/z.lua --init fish enhanced once echo | psub)  # Fish Shell 初始化
iex ($(lua /path/to/z.lua --init powershell enhanced once echo) -join "`n") # Power Shell 初始化

然后重新登陆,即可使用。

用户评价:

“我喜欢它的原理,我在命令行下面的行为十分有规律,并且我十分懒惰,懒得管理和维护一套书签或者路径别名。“

“总之,z.lua 做到了它所宣称的目标。如果你需要快速的在目录间切换,它可能是最好的选择。“

”我终于可以在自己的树莓派1上使用 autojump 类似的功能了,而不用像以前传统 autojump 那样每次打开终端都要等待 30 秒。”

基本使用:

cd 到一个包含 foo 的目录:

z foo

cd 到一个以 foo 结尾的目录:

z foo$

对长路径使用多个关键字进行匹配:
假设路径历史数据库(~/.zlua)中有两条记录:

10   /home/user/work/inbox
30   /home/user/mail/inbox

“z in”将会跳转到 /home/user/mail/inbox 因为它有更高的权重,同时你可以传递更多参数给 z.lua 来更加精确的指明,如 “z w in” 则会让你跳到 /home/user/work/inbox。

交互选择:

使用 -i 参数进行跳转时, 如果有多个匹配结果,那么 z.lua 会给你显示一个列表:

$ z -i soft
3: 0.25   /home/data/software
2: 3.75   /home/skywind/tmp/comma/software
1: 21     /home/skywind/software
> {光标位置}

然后你按照最前面的序号输入你想要去的地方,比如输入 3 就会进入 /home/data/software。如果你不输入任何东西直接按回车,那么将会直接退出而不进行任何跳转。

PS:交互选择同时支持 “-I” 参数(大写 i),让你可以使用 fzf 在多项结果进行快速选择(如果系统里面安装了的话)。

快速回到父目录:

“-b” 选项可快速回到某一级父目录,避免重复输入 “cd ../../..”,一般把 “z -b” 别名成 “zb” 命令:

  • (没有参数):cd 到项目根目录,即跳转到父目录中包含 (.git/.svn/.hg) 的地方。
  • (单个参数):cd 到最近一级以关键字开头的父目录中。
  • (两个参数):对当前目录进行字符串替换,然后 cd 过去。

使用举例:

# 一直向上退到项目根目录(就是里面有一个 .git 目录的地方)
~/github/lorem/src/public$ zb
  => cd ~/github/lorem

# cd 到第一个以 g 开头的父目录
~/github/vimium/src/public$ zb g
  => cd ~/github

# 快速回到 site 目录
~/github/demo/src/org/main/site/utils/file/reader/whatever$ zb si
  => cd ~/github/demo/src/org/main/site

# 将 jekyll 替换为 ghost
~/github/jekyll/test$ zb jekyll ghost
  => cd ~/github/ghost/test

向后跳转同样也支持环境变量 $_ZL_ECHO(用来显示跳转结果),这样为搭配其他工具提供了可能性(并不需要改变当前工作目录):

# 假设我们位于 ~/github/vim/src/libvterm
# 打开 $_ZL_ECHO 用于在每次跳转后调用一次 pwd 显示当前目录
$ _ZL_ECHO=1

# 看看我项目根目录(有 .git 那个)目录里有什么?
$ ls -l `zb`
  => ls -l ~/github/vim

# 检查 "<项目根目录>/logs" 下面的日志
$ tail -f `zb`/logs/error.log
  => tail -f ~/github/vim/logs/error.log

# 查看一下某一级父目录里有些啥
$ ls -l `zb git`
  => ls -l ~/github

Bonus:“zb ..” 相当于 “cd ..”,“zb …” 相当于 “cd ../..”,而 “zb ….” 相当于 “cd ../../..” 等等。 最后 “zb ..20” 等同于调用 “cd ..” 二十次。

常用技巧:

推荐一些常用别名,放在你的配置文件中:

alias zc='z -c' # 严格匹配当前路径的子路径
alias zz='z -i' # 使用交互式选择模式
alias zf='z -I' # 使用 fzf 对多个结果进行选择
alias zb='z -b' # 快速回到父目录

z.lua 可以方便的导入 z.sh 的数据(他们格式相同):

cat ~/.z >> ~/.zlua

还可以导入 autojump 的数据:

FN="$HOME/.local/share/autojump/autojump.txt"
awk -F '\t' '{print $2 "|" $1 "|" 0}' $FN >> ~/.zlua

更多内容,参考项目文档:

https://github.com/skywind3000/z.lua

Loading

Posted in 随笔 | Tagged | 4 Comments

十行代码实现命令行书签

路径书签/别名,用来给目录取个名字,要用时快速跳转,它不是用来代替:z.lua / z.sh / autojump 这类第一梯队的 cd 辅助工具的,而是作为他们的一个补充。

先前我想找个现成的路径书签的小插件,找到这个:pm

把现有目录添加成书签要:

pm add my-project

跳到这个书签对应的目录要:

pm go my-project

然后列出所有书签要:

pm list

删除书签要:

pm remove my-project

我又看了好几个书签软件,都大同小异,又难用,实现又啰嗦,这玩意儿居然写出 500 行以上的代码来,真是匪夷所思。所以我打算用十行代码实现一个更优雅的书签功能。

目标1:少打字

同样一个功能多打一个字母,做一千次就多打了 1K 的内容,能省则省,我不明白为什么这些插件做的都那么啰嗦,输入完命令名还得再输入 add/remove/go/list 之一的参数,然后才是书签名,要我来做,我会把命令名起短一点,比如叫做 m :

m         # 列出当前所有书签
m foo     # 跳转到名为 foo 的标签
m +foo    # 将当前路径添加成书签 foo
m -foo    # 删除名为 foo 书签
m /foo    # 搜索名称里包含 foo 的书签

大部分时候都频率最高的就是 “跳转” 和 “列出所有书签”,所以尽可能的减少他们输入的字符数,m foo 就是跳转到名字为 foo 的书签,比 pm go foo 少打四个字符,m 后面没参数,就是列出所有书签,pm list 少打六个字符。

其他几项功能也比 pm 少打很多字,用 +/- 三个符号代表:增加,搜索和删除,也很直白。

目标2:代码少

我实在不明白一个简单的插件为什么会写成 500-600 行的翔。我们充分利用 shell 的功能,那么把当前目录添加到书签,就是:

ln -snf "$(pwd)" "$MARKPATH/$1" 

其中 $MARKPATH 指向 ~/.local/share/marks 之类的地方,可以自定义,添加书签就是在 $MARKPATH 下面做一个软连接,指向当前目录即可。

删除书签:

rm -i "$MARKPATH/$1" 

删除书签就是删除软连接,还会用 rm 命令的 -i 参数问下你是否真的要删除。

跳转书签:

cd -P "$MARKPATH/$1"

不就完了?使用 -P 参数跳转到实际路径,搞那么多花花绕干嘛?

其他的搜索书签就是 find 命令,列出书签就是 ls 命令格式化一下。

实际代码

实际代码用 case 来判断参数前缀,增加了一些边际情况处理,保存成 m.sh

(点击 more/continue 继续)

Continue reading

Loading

Posted in 编程技术 | Tagged , | Leave a comment

Nas 系统的虚拟化方案

对搞技术的人来说,Nas 是个理想的玩具,既然是程序员用的 Nas ,自然要专业一点,不能像小白一样买台威联通或者群晖往哪里一放就行,如果这样,就没有必要继续往下读了。

就像有人喜欢买成品车,有人喜欢自己改装车;有人喜欢傻瓜相机,有人喜欢机械相机。如果你喜欢 DIY,想让自己家里的硬件发挥更大用途,让自己的 nas 系统更专业些,那么请继续。

有人说,生命的意义在于奉献;还有人说,生命的意义在于付出;然而对于 Nas 玩家来说,生命的意义只有两个字 — “折腾”。

有人问:“Nas 还能玩出一朵花来?”,答案是:“当然能”,折腾 Nas 第一步就是上虚拟化环境,有这个基础,后面才能更好的搞其他东西。所以今天我们先把 Nas 虚拟化这个纲领性的问题给说清楚说透彻。

Nas 系统为什么要虚拟化?

首先是让一台物理机可以安装多个不同的隔离的操作系统,Nas 很多都是魔改 Linux,一机多用的话,除了可以自由的安装其他主流 Linux 发行版外,你还能装台 Windows 来跑迅雷。

其次,而对于程序员,往往还需要另外一个干净的标准 Linux 发行版作为一个开发/折腾的环境,比如 Ubuntu / Debian / Centos 这些,虚拟化后,你可以自由的折腾你的发行版,通过虚拟机隔离后,你乱折腾自己的开发环境也不会把 Nas 弄挂,把自己的数据弄飞。

最后,资源分配更加灵活,系统/磁盘级别的备份迁移和恢复也可以很方便的实现。

Continue reading

Loading

Posted in 未分类 | Tagged | 1 Comment

KVM 虚拟化环境搭建 – WebVirtMgr

前文《KVM 虚拟化环境搭建 – ProxmoxVE》已经给大家介绍了开箱即用的 PVE 系统,PVE 是方便,但还是有几点问题:

第一:始终是商用软件,虽然可以免费用,但未来版本还免费么?商用的法律风险呢?

第二:黑箱化的系统,虽然基于 Debian ,但是深度改造,想搞点别的也不敢乱动。

第三:过分自动化,不能让我操作底层 libvirt/qemu 的各项细节配置。

PVE 是傻瓜相机,智能又复杂,对小白很友好;WebVirtMgr 是机械相机,简单而灵活。多一个选择始终是好事,何况我们说完 PVE 之后还介绍 WebVirtMgr,那肯定是有它不可代替的优势的。

不管你是在中小公司研究 IT 解决方案,还是搭建自己的 HomeLab,虚拟化是一个绕不过去的砍,现在的服务都不会直接启动在物理机上,成熟的架构基本都是:

物理机->虚拟化->容器

这样的三层架构,也就是说虚拟化是一切服务的基础。通过下面的步骤,让你拥有一套完全开源免费的,属于你自己的,没有任何版权和法律问题的虚拟化环境。

操作系统选择

发行版选择主要以 Debian/Ubuntu LTS Server 为主,二者我并无偏好,选择你趁手的即可。Debian 每两年一个大版本,Ubuntu LTS Server 也是每两年一个大版本。也就是说每年都有一个最新的,他们的支持周期都是五年以上,去年发布的 Debian 9 ,今年是 Ubuntu 18.04 LTS,明年又是 Debian 10。

安装依赖

新安装操作系统以后,先安装必备的包:

sudo apt-get install libvirt-daemon-system libvirt-clients
sudo apt-get install sasl2-bin libsasl2-modules bridge-utils

将 /etc/default/libvirtd 里面的一行 libvirtd_opts 改为:

libvirtd_opts="-l"

Continue reading

Loading

Posted in 未分类 | Tagged | 1 Comment

常用公有云的替换方案

多年的教训换来一句话:“你的数据,你掌握”。归根结底,对于重要数据,最安全的做法不是把它交到别人手中,而是自己保管。

文件云服务:百度盘,DropBox,iCloud,OneDrive

经历了 2015 年末国内网盘服务大面积关停以及百度网盘上面文件被管理员删除,iCloud 私密照片泄露的问题后,我意识到,重要文件应该自己管理,公有云服务做一个补充备份。

  • OwnCloud:老牌开源文件服务,支持移动端,网页版,Win/Mac/Ubuntu 桌面版:

  • NextCloud:OwnCloud 核心团队出走后新做的项目,改了很多老bug,加了新特性:

我更喜欢 NextCloud,文件同步很方便,放视频或者照片上去会帮你自动做成缩略图,再 Web 上方便查看,移动版也可以在线播放上面的音视频,而不必下载本地。

上图是相册插件,集中管理网盘内所有图片,还有更多有意思的插件值得花时间好好探索。我做过个镜像,可以用下面的 Docker compose 配置文件一键安装:

Continue reading

Loading

Posted in 未分类 | Tagged | 1 Comment

提高效率从编写 init.sh 开始

有部分人不太愿意定制自己的终端配置,因为:“服务器太多,怎么可能每台都去定制,所以都用默认配置,习惯了就好”。其实道理很简单,算笔账就清楚了,除非你是 SA 每天管理上千台服务器,程序员的话,每天接触的开发服务器也就五台以内。既然 90% 的利益都在那三五台机器上,还在纠结 10% 的事情,这就叫不明智。

还有人担心这 10% 的时间偶尔到裸环境下不适应了,所以拒绝 90% 的时间使用高级配置。这是我听过最荒谬的理由,我天天自己开车上下班,偶尔骑下自行车我也不会忘记怎么骑车。更不因为偶尔需要时怕不会骑了而把汽车卖了每天都坚持骑单车,或者干脆就拒绝学汽车驾驶,拒绝提高自己的车技。我路由器上连 bash 都没有,只有个 busybox 的残缺 shell ,照着理由我要去迁就路由器么?这种说法要不就是看不清楚自己核心利益在哪里,要不就是没体验过汽车快起来可以比单车快几倍。

何况不管是程序员还是 SA,做好配置的同步工作也就行了。如果可以花固定的时间,让终端工作效率提升一倍以上,这种一次性的投资为何不做呢?所以接下来讨论下终端环境下各种配置应该如何管理,如何同步的。

Continue reading

Loading

Posted in 未分类 | Tagged | Leave a comment

千万别混淆 Bash/Zsh 的四种运行模式

Bash/Zsh 有四种不同运行模式,你的 bash 配置写错地方的话,不但会拖慢 bash 的速度,还会发生明明写了登陆配置但是就是没生效的情况。

第一个维度:interactive mode / non-interactive mode

Bash 的 交互模式(interactive mode) 是指你直接输入:

bash

以后 bash 出现一个 “$>” 的 PROMPT,等待用户不断的输入指令,输入 “exit” 或者按了 CTRL+D 才会结束。你 ssh 登陆到一台电脑,或者命令行下面打 bash ,后面没有参数的话,进入的都是交互模式。

非交互模式(non-interactive mode) 是指你用 bash 运行一个命令或者脚本,运行完 bash 就退出那种:

bash -c "echo 123"
bash script.sh

上面这两种情况下,bash 运行完脚本,就退出了,不会出现 PROMPT,也不会等待用户输入新指令。

境变量 $- 里如果有字符 i 的话,代表是一个 interactive shell,否则是 non-interactive mode,我们可以简单测试一下:

$> [[ $- == *i* ]] && echo "Interactive" || echo "Not interactive"
Interactive
$>  bash -c '[[ $- == *i* ]] && echo "Interactive" || echo "Not interactive" '
Not interactive

登陆过后的 shell 都是交互模式的,再交互模式下直接检测 $- 得到 “Interactive” 的结果,而bash 直接运行命令属于非交互模式,所以输出 “Not interactive”

再写一个脚本:check_interactive.sh 继续验证:

#! /bin/bash
[[ $- == *i* ]] && echo "Interactive" || echo "Not interactive"

检验一下:

$> source check_interactive.sh
Interactive
$> bash check_interactive.sh
Not interactive
$> bash -c "source check_interactive.sh"
Not interactive

在 Bash 中,source <文件名> 是在当前 bash shell 进程内执行脚本,效果和直接敲里面的命令一样,所以是交互模式。而 bash <文件名> 是启动一个新的 bash 进程执行脚本,所以是非交互模式。

因此,我们平时写的一大堆 bash 配置,都是针对 “交互模式” 的,如果让 bash 执行条命令都要去运行各种初始化脚本的话,效率太低了,所以 ~/.bashrc 开头就有一句判断:

# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return

或者写为:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

就是为了避免非交互模式随便运行一条命令都要解析后面的各种配置用的。

当然,新版本的 bash 如果以非交互模式启动,会直接跳过 ~/.bashrc 的解析,而这几行 bashrc 中的检测为了兼容被保留了下来。

因此,如果我们不确定 bash/zsh 的版本和行为,又自己从头开始写配置的话,需要在配置开头增加相应的检测代码,避免不必要的工作。

(点击 more/continue 继续)

Continue reading

Loading

Posted in 随笔 | Tagged , | Leave a comment