你可能不知道的shell技巧

只是一些适当的抛砖,未作深刻讨论,不足以当作教程,想完整学习的看官请查阅权威资料!

cd  -

返回上一次进入的目录。等价于cd $OLDPWDnginx

若是你是刚进入终端界面,就不存在上一次的目录,那么执行这个命令将报错:cd: OLDPWD not set。除非你至少执行过一次cd操做docker

!!

执行上一条命令。shell

echo '原罪'
!!

你会看到两个原罪express

若是你有一个命令少打了个什么单词,那么这个功能实在是方便:api

原罪大sb
echo !!

history

查看你以前执行过的命令。数组

$?

查看上一个执行的命令的状态。默认值是0,也就是说没报错。
有一个用处就是你能够用来判断是否要继续往下执行bash

if [ "$?" -ne 0 ]
then
  echo "Error and exix"
  exit $?
fi

若是你的程序容不得半点错误,并且几乎每一步你都须要判断有没有报错,那么改一下模式就行了:服务器

# 设置模式,一旦进程或者子进程返回的状态不是0,那么就直接退出
set -e

# 开始执行代码

test

这是一个内置的检验函数,简写是:[ expression ],也就是咱们常在if中使用的ssh

a=2

test $a -eq 2
echo $?
# 0     测试正确

test $a -eq 3
echo $?
# 1     测试错误


if [ $a -eq 2 ]
then
  # of course
fi

pwd -P

查看当前所在目录,意味着软连接的目录将显示真实的路径函数

reboot

重启电脑。危险操做,慎用

reboot

# 若是没有权限
sudo reboot

set -x

打印出执行的命令,并在命令前加上+号

# vi test.sh
set -x
  
me="Who am i"
echo ${#me}
sh test.sh

# + me='Who am i'
# + echo 8
# 8

: > FILE

置空文件内容并保存。
:实际上是个空操做,能够单独使用

if xxx
then
  :
else
  # run  
fi

shift

从左侧开始删除位置参数

# 模拟位置参数
set aa bb cc

echo $@
# aa bb cc

shift
echo $@
# bb cc

shift
echo $@
# cc

CDPATH

和PATH相似,但这个变量是给cd用的。
你想cd进一个目录,可是这个目录不在当前工做目录,那么shell就会去CDPATH的路径下找

# PhpstormProjects目录下有一个 user-api 目录
CDPATH=$CDPATH:$HOME/PhpstormProjects/

# 当前目录:$HOME
cd user-api
# 当前目录:$HOME/PhpstormProjects/user-api

CDPATH能够放在.bash_profile中

2>&1

输出重定向,将标准错误重定向为标准输出
一些logs输出实际上是走的标准错误输出的,因此你想用管道之类的作额外处理的话,十分抱歉。

# 想查看最后一行的log

# 抱歉。这样没法经过管道,直接所有打印出来了
docker logs some-container | tail -1

# 好的。管道正式开放
docker logs some-container 2>&1 | tail -1

有时候,你想捕获错误信息,并使用他,或者存入变量,那么也可使用输出重定向。

注意:2>&1 中间不能有空格哦

dirname $0

在shell执行脚本文件中,精确的找到当前文件所在的目录。

# file.sh

current_dir=$(dirname $0)

cal

快速查看日历

# 查看当前月的日历
cal

      十月 2018         
日 一 二 三 四 五 六  
    1  2  3  4  5  6  
 7  8  9 10 11 12 13  
14 15 16 17 18 19 20  
21 22 23 24 25 26 27  
28 29 30 31    

# 查看9月日历
cal 9 2018
       
       九月 2018         
日 一 二 三 四 五 六  
                   1  
 2  3  4  5  6  7  8  
 9 10 11 12 13 14 15  
16 17 18 19 20 21 22  
23 24 25 26 27 28 29  
30 



# 查看一年12个月的日历
cal 2018

cat > FILE <<

利用行内输入重定向把内容写入文件。在作一些自动化脚本的时候比较有用,兼顾了格式化和可读性。
这种写法也叫作here document

cat > test.txt <<EOF
你好原罪
  换了一行,还带空格
十年磨一剑
EOF

好的,test.txt中已经写入了相关文字,格式一致。不信你就cat test.txt试试。

网上常常看到一些教程,先vi file,而后把某段内容复制进去,而后:wq一下。我去,哪有那么多时间理你啊。如今,你能够这么说:把这段执行一下便可!

grep -v grep

这个看官可能想找某个正在运行的进程

ps aux | grep nginx

细心的你会发现,无论有没有找到nginx相关的进程,都会显示一个进程

fwh1990           1134   0.0  0.0  4268060    828 s002  S+    3:52下午   0:00.00 grep nginx

咱们略施小计便可去除这种无用进程

ps aux | grep nginx | grep -v grep

好的,还你一个清爽的输出。

readonly

设置一个只读变量。意味着不能再修改了,修改会报错呦。

readonly me='原罪'

# 打印原罪
echo $me

# 马上报错
me='小弟'
# -bash: me: readonly variable

array[*]

shell是有数组的

arr[0]='你好'
arr[1]='原罪'
arr[2]='哥'

echo ${arr[0]}
 # 你好

echo ${arr[2]}
 # 哥

echo $arr
# 你好               等价于 ${arr[0]}

echo ${arr[*]}
# 你好 原罪 哥        所有打印

字符串也能够转换成数组

arr='你好 原罪 哥'
arr=($arr)

echo ${arr[1]}
# 原罪

${parameter:?}

要求参数必须填,不然报错。去除繁琐的if判断

# vi test.sh
echo ${1:?}


#shell:
sh test.sh
# test.sh: line 1: 1: parameter null or not set

固然了,也能够设置报错内容${parameter:?error_value}

unset

是的,shell变量也能够删除(包括函数)

# 变量
aa=123

echo $aa
# 123

unset aa
echo $aa
#
# 函数
testMe () {
  echo 'done'
}

testMe
# done

unset testMe
testMe
#

ssh-copy-id USER@IP

这是一个mac下的命令,就是把公钥当即部署到服务器对应用户的 ~/.ssh/authoried_keys 文件中。身边的朋友都以为这个命令挺实用的!