Shell 的偷懒技巧

近小半年工作使用 shell 的频率越来越高,为了防止一些无用的重复操作浪费太多时间,学习和摸索了一些乱七八糟的技巧,以帮助我更「懒」地使用 Shell。

我有很多老花样,比如,换个 Shell……

Z shell(Zsh)作为一个 Shell,以强大的功能性、便捷性与极佳的兼容性及扩展性,为广大命令行爱好者所推崇。

如果正在使用 Linux(包括 Windows 上的 WSL)或 macOS 系统,我十分推荐使用 Zsh 作为日常交互的选择。

安装 Zsh

Zsh 在众多发行版系统中均可直接安装,可以使用各自的包管理工具(如 APT、Yum 及 Homebrew)直接进行安装,更多详情请参考《Installing ZSH》

这里举个例子:

1
apt install zsh -y

安装 Oh My Zsh

Zsh 本身安装完是需要经过一番配置才够好用,不过这里有另外一个项目能够帮我们快速上手,大名鼎鼎的 Oh My Zsh

使用方法也不难,使用 curl 或 wget 下载安装脚本并进行安装即可。

1
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
1
sh -c "$(wget https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)"

如果提示错误,请记得给终端走代理。

这个时候,就有一个开袋即食的 Zsh 了!

配置 Zsh

安装 Zsh 只是基础,目的是为了用上强大的插件,让命令行在使用中更佳高效便捷。

z

z 这个插件和 autojump 差不多,会记录之前使用过程中访问的目录及频次,但不依赖 Python,并且 Oh My Zsh 中内置,直接启用就可以使用。

1
vim ~/.zshrc

在配置文件中找到 plugins= 这行,默认只开启了 git 插件,这里在后面加上 z,用半角空格隔开。

1
plugins=(git z)
1
source ~/.zshrc

不过现在的 z 还无法使用,因为在启用了 z 之后还没有切换过目录。

随便切换几次目录,然后使用 z keyword 就可以跳转含有对应关键字的路径了。

直接敲 z 也可以看到目前为止访问过了目录以及权重。

工作时频繁在多个目录中切换时,z 可以节省非常多的时间。

zsh-autosuggestions

zsh-autosuggestions 插件是在 shell 中键入命令的时候,会依据以往的历史命令,给出最可能的提示。

如果提示的命令是你需要的,可以直接按方向键右直接补全该命令,可谓简单高效。

zsh-autosuggestions

安装方法也很简单,直接使用 git 将仓库 clone 到指定位置。

1
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

然后再启用插件,启用方法和 z 一样。

1
vim ~/.zshrc
1
plugins=(git z zsh-autosuggestions)
1
source ~/.zshrc

但因为环境的不同,有时可能会报警目录权限不安全。

这时候重新赋予一下权限即可。

1
chmod 755 /root/.oh-my-zsh/custom/plugins/zsh-autosuggestions

不过默认提示的灰色在暗色背景主题下太难识别,可以改变一下提示文字的颜色。

1
vim ~/.zshrc

新起一行,加上以下内容:

1
2
# zsh-autosuggestions
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=6'
1
source ~/.zshrc

这个颜色就比较顺眼了。

在 PowerShell 上使用 z

PowerShell 上其实也是可以使用 z 的,只要使用 scoop 包管理工具直接安装即可。

安装 scoop 的过程在此省略。

1
scoop install z

注意要使用管理员权限。

使用方法和 Linux 上没有区别。

同时 scoop 也可以安装 sudo,这样即使忘记用管理员权限打开 Terminal,也能够临时提权执行操作,方便不少。

插件不够,函数来凑

插件固然帮我解决了很多问题,但不是总有办法找到工具,这时候就需要一点点动手能力了。

在工作中,经常会面临到重复使用同个工具,使用同样的参数,唯一的不同点就是目标不同。

每次都去历史命令里修改,找命令要花时间,修改也要花时间,有没有办法把这些内容重新定义成一个新命令直接了当地使用呢?

答案当然是有的。

我常用到的两个工具分别是 dirsearchnmap,这两个工具使用起来会定义非常多的参数,如 dirsearch,我常用的命令如下:

1
./dirsearch.py -u "target-url" -e * --max-retries=2 --timeout=2 -t 10 -x 400,403,405,500,502,503,999

而 nmap 呢,则是这样:

1
nmap -v -sV -p 1-65535 target-ip -oN ~/nmap/nmap-target-ip.txt

在连续的工作中,修改命令再执行倒也还好。

但经常在结束前一天的工作,开始后一天的工作时,刚开始找命令要花一些时间。

即使本地保存了,那也得复制粘贴不是。

基于此,我就想到把这些常用带参命令定义成新的命令,然后来使用它们。

由于 Bash 与 PowerShell 不同,这里分两部分。

Bash

打开 .bashrc 文件,Zsh 则打开 .zshrc

1
vim ~/.bashrc

如 dirsearch,这里就可以这么写:

1
2
3
4
function dirs(){
cd ~/dirsearch
./dirsearch.py -u "$1" -e * --max-retries=2 --timeout=2 -t 10 -x 400,403,405,500,502,503,999
}

因为 dirsearch 没加环境变量,所以要切到相应目录去执行。

指定绝对路径目录执行我也试过,会一直提示找不到字典,所以干脆切个目录算了。

nmap 呢,就可以这么写:

1
2
3
function nmp(){
nmap -v -sV -p 1-65535 $1 -oN ~/nmap/nmap-$1.txt
}

改完后保存,初始化一下。

1
source ~/.bashrc

Zsh 还是初始化对应的文件:

1
source ~/.zshrc

这时候就可以直接执行类似以下的命令来使用:

1
2
dirs www.qq.com
nmp 114.114.114.114

同理,使用类似的方法,可以用两个命令快速开关终端中的代理开关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Proxy On
function pon(){
export http_proxy=http://127.0.0.1:37777
export https_proxy=http://127.0.0.1:37777
echo -e "------- Proxy ON! -------"
}
# Prxoy Off
function pof(){
unset http_proxy
unset https_proxy
echo -e "------- Proxy OFF! ------"
}
# Default Proxy
unset http_proxy
unset https_proxy

这样每次不用临时贴命令或者开关系统代理来让终端走代理了。

PowerShell

PowerShell 的写法和 Bash 类似,唯一不同的是需要先定义传参的变量,然后再调用,不如 Bash 可以默认传参。

dirsearch 如下:

1
2
3
4
5
6
Set-Alias dirs Set-dirsearch
function Set-dirsearch($url)
{
cd C:\Pentest\dirsearch\
.\dirsearch.py -u "$url" -e * --max-retries=2 --timeout=2 -t 10 -x 400,403,405,500,502,503,999
}

nmap 如下:

1
2
3
4
5
Set-Alias nmp Set-nmap
function Set-nmap($ip)
{
nmap -v -sV -p 1-65535 $ip -oN C:\Neko7ina\Syncthing\Desktop\Pentest\nmap\nmap-$ip.txt
}

代理如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$Env:http_proxy=""
$Env:https_proxy=""
Set-Alias pon Set-Local-Proxy
Set-Alias pof Clear-Local-Proxy
function Set-Local-Proxy
{
$Env:http_proxy="http://127.0.0.1:37777"
$Env:https_proxy="http://127.0.0.1:37777"

Write-Host "------- Proxy ON! -------"
}

function Clear-Local-Proxy
{
$Env:http_proxy=""
$Env:https_proxy=""

Write-Host "------- Proxy OFF! ------"
}

结语

虽然折腾起来会稍微花点时间,但和以后偷懒的时间比起来,这又算得了什么呢?