Bash 快速入门
基础知识
三级权限
目录的写权限是写入目录表的权限,例如文件的创建和删除、更名。写入目录下的文件,不需要目录的写权限。
目录有执行权限意味着 分析路径名 过程中可检索该目录,例如 cat /a/b/c
,则 /a
/a/b
需要有 x
权限,c
需要有 r
权限。
Sticky (t) 权限:文件而言目前没有用。但若目录有 wt 权限,则只能被文件主删除。
权限验证过程:进程的主、组属性与文件的主、组属性比较。root 不受上述限制。
umask 用于设置初始权限。umask 022
可放到 bash 文件中,只在此文件生效。
SUID 权限
实际 UID 和有效 UID:后者是用来进行权限判断的 UID。
chmod u+s query
SUID 使得用户可以通过文件主提供的程序,以文件主的权限访问文件,但这种访问依赖于文件主提供的程序,进行有限的访问
shell 的启动形式
- Login Shell:通过登录启动的 Shell
- 执行 profile 文件。
/etc/profile
~/.bash_profile
~/.bash_login
~/.profile
- 推出之执行 logout 文件。
- 执行 profile 文件。
- Interactive Shell:交互式解释器的 Shell。通过输入命令回车可得到命令结果
- 执行
$HOME/.bashrc
- 执行
- Non Interactive Shell:通过
bash scriptname
执行的脚本
BASH 的执行形式
- Fork 执行
- bash < cmd
- bash cmd
- bash -x cmd
- bash cmd args
- Execve 执行
- . cmd args
重定向
stdin 的 fd = 0
输入
-
sort < file
将 file 定向为sort
的 stdin -
使用定界符:
cat << TOAST * Now : `date` * My Home Directory is $HOME TOAST
定界符内转义等同于双引号
加单引号禁止替换
cat << 'TOAST' * Now : `date` * My Home Directory is $HOME TOAST pwd
-
从命令行获取信息作为标准输入
<<<word base64 <<< meiyoumima base64 <<< 'mei you mi ma
输出
stdout, fd = 1; stderr, fd = 2
> fname
覆盖输出>> fname
追加输出2> fname
仅 stderr 输出2>&1
stderr 合并到 stdout 输出- 管道
ls -l | grep '^d'
前一命令的 stdout 作后一命令的 stdincc try.c -o try 2>&1 | more
前一命令的 stdout+stderr 作为下一命令的 stdin
开头
#!/bin/bash
表明解释器。
变量
定义
**等号两侧不许多余空格 **
myString="hallo!"
myFiles=`ls -al` # 取执行结果
访问
echo $myString
echo ${addr}
默认:未定义变量,变量值为空字符串
-
set -u
当引用一个未定义的变量时,产生一个错误 -
set +u
当引用一个未定义的变量时,认为是一个空串(默认情形) -
set -x
执行命令前打印出 shell 替换后的命令及参数, 为区别于正常的 shell 输出, 前面冠以 + 号 -
set +x
取消上述设置
打印
- echo
- printf
printf '\033[01;33mConnect to %s Network\n' $proto
编辑文件
可以使用 ed
命令
printf 'Input IP address of server computer: '
read addr
ed myap.conf > /dev/null 2>&1 << TOAST
/SERVER
.d
i
SERVER $addr
.wq
TOAST
echo Bye
替换
now=date
以命令 date 的 stdout 替换 date
now=$(date) 以命令 date 的 stdout 替换 $(date)
读命令行参数
$0
脚本文件本身的名字$1
$2
1 号命令行参数, 2 号命令行参数,以此类推$#
命令行参数的个数$\*
等同于”$1 $2 $3 $4 …”$@
等同于”$1” ”$2” ”$3”$?
上一命令的返回码
判断返回值是否为 0
if [ $? -ne 0 ]; then
exit_with_error "Failed to build."
exit 1
fi
条件
test
/usr/bin/[
程序:要求其最后一个命令行参数必须为 ]
(/usr/bin/test
无此要求)
test -r /etc/motd
[ -r /etc/motd ]
文件特性检测
-f
普通文件
-d
目录文件
-r
可读
-w
可写
-x
可执行
-s
size>0
test -r /etc/motd && echo readable
[ -r /etc/motd ] && echo readable
字符串比较
["$a" = ""] && echo empty string 注意:$a 的引号
test $# = 0 && echo "No argument“
level=8
[ $level=0 ] && echo level is Zero
整数的比较
-
-eq
= -
-ne
≠ -
-gt
> -
-ge
≥ -
-lt
< -
-le
≤
例:
test `ls | wc -l` -ge 100 && echo "Too many files"
逻辑运算
! NOT(非) -o OR (或) -a AND (与)
下面的语句判断参数是否为空:
if [ ! -n "$1" ] ;then
echo "you have not input a word!"
else
echo "the word you input is $1"
fi
短路条件
pwd
DIR=/usr/bin
[ -d $DIR ] && (
cd $DIR
echo "Current Directory is `pwd`"
echo "`ls | wc -l` files"
)
pwd
(list)
在子 shell 中执行命令表 list
{list;}
在当前 shell 中执行命令表 list
if 分支
if condition
then list
elif condition
then list
else
list
fi
case 分支
case word in
pattern1) list1;;
pattern2) list2;;
...
esac
expr
shell 不支持除字符串以外的数据类型,不支持加减乘除等算数运算和关于字符 串的正则表达式运算
需要这些功能,借助于 shell 之外的可执行程序 /usr/bin/expr 实现
x=`expr $a \\\* \\( $b + $c \)`
y=`expr \( $a + 4 \\< $b \) \& \( $c != 8 \)`
x=`expr $a '\*' '(' $b + $c ')'`
y=`expr '(' $a + 4 '<' $b ')' '&' '(' $c != 8 ')'`
搞颜色
echo -e "\033 [30m 黑色字 \033 [0m"
echo -e "\033 [31m 红色字 \033 [0m"
echo -e "\033 [32m 绿色字 \033 [0m"
echo -e "\033 [33m 黄色字 \033 [0m"
echo -e "\033 [34m 蓝色字 \033 [0m"
echo -e "\033 [35m 紫色字 \033 [0m"
echo -e "\033 [36m 天蓝字 \033 [0m"
echo -e "\033 [37m 白色字 \033 [0m"
循环
例:等待文件 lockfile 消失:
while test -r lockfile
do
sleep 5
done
for i in `seq 1 254`
do
ping -c 1 -w 1 192.168.0.$i
done
遍历参数
for i
do
PIDS=`ps -e | awk '/[0-9]:[0-9][0-9] '$i'$/ { printf("%d ", $1);}'`
if [ "$PIDs" = "" ]
then
echo -e "No \"$i\" is killed."
else
echo "kill $PIDS ($i)"
kill $PIDS
fi
done
退出
使用 exit RETVAL
exit 0 #正常退出
取扩展名
basename xx.txt .txt
# result is xx
函数
申明
exit_with_error() {
echo -e "\033 [31m[ERROR]\033 [0m$1"
}
调用
exit_with_error "Failed to build."