综合

bash 脚本要点(shell)

2016-09-11  本文已影响128人  michael_jia

bash:Bourne Again shell,是 Linux 上的标配 shell;对于想学习 shell 的人来说,无论是新手,还是想进一步提高 shell 编程能力的高级用户,bash 都是比较好的选择。

  1. For learning Bash, try the BashGuide.
  2. 引号 Quotes,熟读并测试!
  3. 命令参数 Arguments,熟读并测试!
  4. Word Splitting
  5. Process Management,有价值!

条件判断

if [  ]; then
...
elif [  ]; then
...
else
...
fi
case $HOST in node*)
    your code here
esac
  1. script_dir=$( cd ${0%/*} && pwd -P ) 文件目录【从右侧开始删除,直到遇到第一个 /:最短删除】
  2. ${0##*/},相当于 "$(basename ${0})" 文件名【从左侧开始删除,直到最后一个/:最长删除】
  3. g_nap=${url##*/}; g_nap=${g_nap%%\?*} 取 url 的 path 的最右侧一节;http://host:port/p1/p2/p3?query,取到的是p3;
计算赋值
i=0
i=$(expr $i + 1)
i=`expr $i + 1`
i=$(($i + 1))
i=$[$i + 1]
i=$((i + 1))
i=$[i + 1]
  1. $(command)
  2. `command`
  3. $(...) is preferred over `...` (backticks),建议使用 $(...);
$(( EXPRESSION ))
$[ EXPRESSION ]

If a command is terminated by the control operator ‘&’, the shell executes the command asynchronously in a subshell. This is known as executing the command in the background. The shell does not wait for the command to finish, and the return status is 0 (true).

if [ "$EUID" -ne 0 ]; then
  echo "Please run as root"
  exit
fi

变量、函数和引号

The shell parses your command-line into a command name and a list of arguments. 
It uses white-space (tabs and spaces) to split the command into these parts.
Then it runs the command, passing it the argument list.

Perl one-liner 这个工具也很有用,可以分析参数。Smylers 是个人物。

错误

双引号

命令

subshell

awk | gawk

sed -n '$=' filename
awk 'END {print NR}' filename
grep -c '' filename

命令行参数

for last; do true; done
echo $last
如何异步签出代码并构建?

source /home/git/devops/gwph.git.hooks/www.post-receive.gulp >&- 2>&- &

何为重定向?

符号 & 比较神奇,在命令后面加 & 就会在后台运行;还可以用来重定向,原来一直对重定向模糊,今天前端构建时要在签入代码之后异步构建页面,看了两篇文章才彻底明白其原理:

if cmp a b &> /dev/null  # Suppress output.
then echo "Files a and b are identical."
else echo "Files a and b differ."
fi
bash shell 特殊变量
No. Variable Description
1 $0 The filename of the current script.
2 $n These variables correspond to the arguments with which a script was invoked. Here n is a positive decimal number corresponding to the position of an argument (the first argument is $1, the second argument is $2, and so on).
3 $# The number of arguments supplied to a script.
4 $* All the arguments are double quoted. If a script receives two arguments, $* is equivalent to $1 $2.
5 $@ All the arguments are individually double quoted. If a script receives two arguments, $@ is equivalent to $1 $2.
6 $? The exit status of the last command executed.
7 $$ The process number of the current shell. For shell scripts, this is the process ID under which they are executing.
8 $! The process number of the last background command.

The exit command in bash accepts integers from 0 - 255, in most cases 0 and 1 will suffice, however there are other reserved exit codes that can be used for more specific errors. The Linux Documentation Project has a pretty good table of reserved exit codes and what they are used for.
保留错误码。错误码在 1-255 之间。用户使用的话,建议在 1-125 之间取值。

备注

Read and execute commands from filename in the current shell environment and return the exit status of the last command executed from filename.
If any arguments are supplied, they become the positional parameters when filename is executed.
Otherwise the positional parameters are unchanged.
The return status is the status of the last command exited within the script (0 if no commands are executed),
and false if filename is not found or cannot be read.

字符串比较请使用一个等号=即可(POSIX标准)
[ STRING1 == STRING2 ]  True if the strings are equal. "=" may be used instead of "==" for strict POSIX compliance.
使用superctl_ok.sh更合适

BASH 基本概念

Bash Component Architecture @ aosabook.org
Brace Expansion:{} 扩展;
Tilde Expansion:~ 扩展;
Variable and Parameter Expansion(PE):变量和参数扩展;

It is vital to understand, however, that Quoting and Escaping are considered before parameter expansion happens, while Word Splitting is performed after. That means that it remains absolutely vital that we quote our parameter expansions, in case they may expand values that contain syntactical whitespace which will then in the next step be word-split.

解析流程
eval 050 规则
Greg's Wiki【wooledge.org】
  1. 首先理解系统调用 execve
    int execve(const char *filename, char *const argv[], char *const envp[]);
    argv:argument vector;
    envp:environment;
  2. 理解 shell 如何将 命令 command 翻译成系统调用;
  3. 实现业务逻辑;
Quote Guidelines
了解 shell
知识点

示例:
cat <<EOF
Usage: $0 [options]
Language-agnostic unit tests for subprocesses.
Options:
-v, --verbose generate output for every individual test case
-h show brief usage information and exit
--help show this help message and exit
EOF

sudo bats 时报告sudo: bats: command not found

$ sudo bats sapiloader.bats
sudo: bats: command not found

解决方案

The error happens because the binary you are trying to call from command line is only part of the current user's PATH variable, but not a part of root user's PATH.
$ sudo env | grep ^PATH 查看 sudo 的 PATH,果然发现不包含 /usr/local/bin,因此:将 bats 改为全路径 /usr/local/bin/bats 就可以正常执行,但不方便,我们改造 ~/.bashrc,加一条语句,创建 sudo 别名(别名优先于命令)即可:
alias sudo='sudo -E env "PATH=$PATH"'
完美解决!

备注

上一篇 下一篇

猜你喜欢

热点阅读