你可能不知道的shell技巧
只是一些适当的抛砖,未做深入讨论,不足以当做教程,想完整学习的看官请查阅权威资料!
cd -
返回上一次进入的目录。等价于cd $OLDPWD
。
如果你是刚进入终端界面,就不存在上一次的目录,那么执行这个命令将报错:cd: OLDPWD not set
。除非你至少执行过一次cd操作
!!
执行上一条命令。
echo '原罪' !!
你会看到两个原罪
如果你有一个命令少打了个什么单词,那么这个功能实在是方便:
原罪大sb echo !!
history
查看你之前执行过的命令。
$?
查看上一个执行的命令的状态。默认值是0,也就是说没报错。
有一个用处就是你可以用来判断是否要继续往下执行
if [ "$?" -ne 0 ] then echo "Error and exix" exit $? fi
如果你的程序容不得半点错误,而且几乎每一步你都需要判断有没有报错,那么改一下模式就好了:
# 设置模式,一旦进程或者子进程返回的状态不是0,那么就直接退出 set -e # 开始执行代码
test
这是一个内置的检验函数,简写是:[ expression ]
,也就是我们常在if
中使用的
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 文件中。身边的朋友都觉得这个命令挺实用的!