Tag Archives:Linux

十行代码实现命令行书签

路径书签/别名,用来给目录取个名字,要用时快速跳转,它不是用来代替: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    # 将当前路径添加成书签 foom -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

千万别混淆 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.shInteractive$> bash check_interactive.shNot 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 anythingcase $- in    *i*) ;;      *) return;;esac

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

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

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

(点击 more/continue 继续)

Continue reading

Loading

自带语法高亮的 cat – ccat

cat 源代码时如果带上语法高亮,会不会让工作效率更高一些呢?我们来做一个吧:

function ccat() {    local style="monokai"    if [ $# -eq 0 ]; then        pygmentize -P style=$style -P tabsize=4 -f terminal256 -g    else        for NAME in $@; do            pygmentize -P style=$style -P tabsize=4 -f terminal256 -g "$NAME"        done    fi}

把上面代码片段放入你的 .bashrc 中,并且安装依赖:

sudo pip install pygments

就可以跟 cat 一样的用法查看文件内容了:

对比下老的 cat 效果:

是不是清爽多了?

有人在网上推荐个类似的工具,Go 语言写的ccat,效果丑死了:

黑色背景下都看不清楚,这个一万多行的 Go 写的效果,比我们 10 行 bash 写的差远了啊。

补充:其他网友推荐的 sharkdp/bat 看了下效果也相当不错,但是你不想下载安装几兆的东西的话,上面十行代码就够了,熟练掌握 Bash,很多事情需要就自己撸,效果也还不错,自己动手丰衣足食,不用网上找,不用求人开发。

Loading

Nano 编辑器可以做些什么?

终端下如果你不喜欢 Vim/Emacs 的话,Nano 是一个不错的选择,它是一个真正意义上的跨平台编辑器,基本上在所有 Linux 发行版上都默认自带 Nano,并且有 Windows 版本。

不少初学 Linux 都很喜欢用 Nano,但是我发现他们很多都是在裸用,既没配置,也一直在用一些比较低效的操作方法。

Q:下面的帮助占三行,很碍眼,能否隐藏?

可以在编辑时使用ALT+x 就可以切换下面的帮助信息,或者在你的~/.nanorc 里面加一行:

set nohelp

效果如下图:

恩,那两行恶心的帮助已经被我们去掉了,需要时还可以用ALT+x 把它切换回来。

Q:如何打开语法高亮?

有的 Linux 发行版自带了/etc/nanorc 文件,里面定义了语法高亮,而另外一些系统可能没有这个定义,你需要在~/.nanorc 中加一行:

include "/usr/share/nano/*.nanorc"

各种语言的语法文件一般位于:/usr/share/nano/ 下面,设置前先确认一下。

Q:怎么编辑 ~/.nanorc,常用设置有哪些?

常见的 nano 配置如下:(点击 more/continue 继续)

Continue reading

Loading

Bash 中文速查表/Cheatsheet (全网最全)

Bash 的知识点向来比较凌乱,有时候写点小脚本,你忘记了条件判断怎么写了,就打开网页搜索一半天;忘记怎么分割字符串,又搜索一半天;忘了怎么解压缩某后缀名,又打开网页搜一半天。

关键大部分搜出来的东西都十分琐碎,东一处,西一处,质量又参差不齐,而且看到一处有些细节有疑问,你还得接着搜索。

连记点笔记也是这一篇那一篇的,用起来找来找去的十分不爽,所以我一怒之下春节期间整理了一份 bash 的 cheatsheet,以图以后有关于 bash 的事情就查看这个文件就够了:

https://github.com/skywind3000/awesome-cheatsheets/blob/master/languages/bash.sh

对于一些工具性的东西,有时候一份速查表比你翻书查网页都高效数倍。


相关阅读:

韦易笑:有哪些命令行的软件堪称神器?

终端调试哪家强?

为什么说 zsh 是 shell 中的极品?

Loading

GDB 从裸奔到穿戴整齐

无数次被问道:你在终端下怎么调试更高效?或者怎么在 Vim 里调试?好吧,今天统一回答下,我从来不在 vim 里调试,因为它还不成熟。那除了命令行 GDB 裸奔以外,终端下还有没有更高效的方法?能够让我事半功倍?

当然有,选择恰当的工具和方法,让 GDB 调试效率成倍的提升并没有任何问题。当然,前提条件是你至少会在使用最原始的 GDB。

裸奔状态:原始的 GDB 命令行

穿上各种衣服前,至少得先学会裸奔,找份简单的 GDB cheat sheet 对照一下:

生产环境中出现崩溃时,因线上服务器一般没有开发环境,也无配套源代码,所以程序崩溃后,如果你懒得把 core 文件拖回到开发机检查,可以先在线上服务器先简单gdb看一下。

GDB命令密密麻麻,常用的也就表格上那几条,比如进去以后第一步先用 bt 查看一下调用栈,info local查看一下本地变量,再配合 up/down 在整个调用栈的不同层次之间上下移动一下,检查各处局部变量的值,print 一下某个表达式,即便没代码,看下符号和反汇编,一般也能调试个七七八八。

碰到复杂点的 BUG,必须配合源代码了,那你得把 core 文件拉到开发环境中,再用 gdb 对照源代码调试,配合 list [行号] 指令查看当前运行的源代码,再配合其他方法进行调试。

那么这时候,如果调试复杂度继续上升,你需要不断的断点,每次 next / step 单步完后你都需要 list 一下前后源代码,或者用 disassemble [函数名/地址] 查看一下指令的话,不少人会感觉到抓狂,这时我们需要给裸奔的 GDB 穿条内裤了。

穿上内裤的 GDB – TUI

这是 gdb 自带的文本界面,使用 gdb -tui 命令启动,比如:

gdb -tui hello

即可打开我们的文本界面:

上方是源代码窗口,下面是 gdb 终端,窗口管理快捷键模仿 emacs,使用 c-x o 进行窗口切换,如果你还想查看指令窗口,可以输入:layout split

然后你单步的时候上面的源代码窗口会跟着滚动,比之前不停的 list 方便不少吧,要看前后源代码可以继续 c-x o 切换窗口后上下滚动。

有时候你 up/down 切换了栈帧后,上面的代码也许来不及更新,那么你用 update 指令,让上面的代码窗口定位到你最新的执行位置,有时也需要 CTRL-L 重绘下整个界面。

在 gdb 自带的 tui 模式中,你不但可以随时查看代码/指令,还可以查看寄存器。好吧,其实 gdb再简陋,本身还是配套了一条内裤的,只是很多人忘记拿出来穿了。

穿上内衣:gdbinit

如果上述文本 TUI的信息不够丰富的话,也许你会对 .gdbinit 感兴趣,~/.gdbinit 是一个 gdb配置脚本,可以设定一些由 python 编写的插件,比如 peda:

在 ~/.gdbinit 上面配置了 peda 后,可以看到命令提示符就从 (gdb) 变成了 gdb-peda$ 。每敲一个单步命令,peda 都会显示出无比丰富的信息,你还可以配置添加更多,配合高亮,你可以得到一个加强版的命令行。

不过这个我用的并不多,因为它会影响 TUI 模式的界面,我不喜欢在我的 gdb 里搞太多乱七八糟的东西。同时,当我们的调试需求继续变得更加复杂,你要不停的断点,频繁的单步,这些传统命令行里不停的输入各种指令显然已经让我们疲惫不堪了,能否直接在界面上查看源代码并且直接在代码上快捷键断点,快捷键单步呢?

可以啊,试试 cgdb。

穿上外套的 GDB:cgdb

CGDB 类似 gdb tui 分为终端窗口和代码窗口:

Continue reading

Loading

Linux 网桥设置

在公司机房的物理机上架设 KVM虚拟化的时候,经常需要配置网桥,先要安装网桥工具:

apt-get install bridge-utils   apt-get install uml-utilities

编辑 /etc/network/interfaces,参考下面配置加入网桥配置信息:

Continue reading

Loading

Linux 硬件时区折腾备忘

前段时间折腾家中 Nas的虚拟化服务,有时候虚拟机系统时间总是快8个小时。Guest这边设好了,到了 物理机就会慢8个小时。网上说只要修改/etc/default/rcS中的 UTC=no就行了,但还是没反映,没办法,一步步找问题。发现在/etc/rcS.d/S05hwclock.sh有这样一段话:

# 2012-02-16 Roger Leigh rleigh@debian.org# - Use the UTC/LOCAL setting in /etc/adjtime rather than# the UTC setting in /etc/default/rcS. Additionally# source /etc/default/hwclock to permit configuration.

Continue reading

Loading

Linux 线上系统调优备忘

大公司呆久了,都会对 SA的依赖十分强烈,很多事情 SA都帮我们搞定了。如今控制成本,没有招聘 SA,又没有购买 VPS,从买物理机开始到 IDC部署,服务器调优,虚拟机管理,全部都是自己来,才发现,安装一台 Linux机器自己玩很简单,但是要达到线上服务器的标准,还有若干调优工作需要做,有 SA的日志是多幸福的事情啊。

物理机设备驱动

Dell服务器默认安装系统后会报找不到驱动:

W: Possible missing firmware /lib/firmware/tigon/tg3_tso5.bin

因为 Debian/Ubuntu 的包都是开源的,默认开源驱动性能不行,于是需要添加 non-free源:

deb http://ftp.de.debian.org/debian main contrib non-freedeb-src http://ftp.de.debian.org/debian main contrib non-free

然后:

apt-get updateapt-get install firmware-linux-free firmware-linux-nonfree

解决 Dell驱动报错问题。

Continue reading

Loading

Posted in随笔|Tagged|2 Comments

Linux 下配置 Iptables 端口转发

经常需要对服务端的端口进行转发映射,让链接A服务器(202.181.55.93:8080)端口的所有tcp数据,forward到B服务器(106.185.43.22:80)端口,比如国内联通出国访问比较快,而电信比较坑爹,如果你家是电信网络,你却想畅快的访问境外的
vps,那么可以在你联通网络的境内服务器上进行这样一个端口映射,你链接境内服务器(201.181.55.93:8080)端口相当于链接境外服务器的(106.185.43.22:80)端口。

Linux内核的 Iptables很强大,它维护一组内核变量,使用 /sbin/iptables命令进行直接规则设置,且通过配置新规则,可以直接支持端口转发,简单在 A服务器上使用下面这个 shell脚本即可:

#! /bin/sh# create forward rule by source interface# http://serverfault.com/questions/532569/how-to-do-port-forwarding-redirecting-on-debianPortForward1() {    local IN_IF=$1    local IN_PORT=$2    local OUT_IP=$3    local OUT_PORT=$4    local IPTBL="/sbin/iptables"    echo "1" > /proc/sys/net/ipv4/ip_forward    $IPTBL -A PREROUTING -t nat -i $IN_IF -p tcp --dport $IN_PORT -j DNAT --to-destination ${OUT_IP}:${OUT_PORT}    $IPTBL -A FORWARD -p tcp -d $OUT_IP --dport $OUT_PORT -j ACCEPT    $IPTBL -A POSTROUTING -t nat -j MASQUERADE}# create forward rule by source ip# http://blog.csdn.net/zzhongcy/article/details/42738285ForwardPort2() {    local IN_IP=$1    local IN_PORT=$2    local OUT_IP=$3    local OUT_PORT=$4    local IPTBL="/sbin/iptables"    echo "1" > /proc/sys/net/ipv4/ip_forward    $IPTBL -t nat -A PREROUTING --dst $IN_IP -p tcp --dport $IN_PORT -j DNAT --to-destination ${OUT_IP}:${OUT_PORT}    $IPTBL -t nat -A POSTROUTING --dst $OUT_IP -p tcp --dport $OUT_PORT -j SNAT --to-source $IN_IP}PortForward1 eth3 8080 106.185.43.22 80# put this file on /etc/network/if-up.d

上面两个函数,一个是针对网卡,一个是针对本地IP设置转发,记得把这个脚本放到/etc/network/if-up.d 下面并设置可执行权限(Debian/Ubuntu),每次开机重启时保证可以运行,即可。

Loading