一般如果某个内容会在之后的脚本里反复用到,此时我们应该把其抽象成变量,比如写个备份MySQL数据的脚本,显然MySQL的IP地址和端口应该提出来作为变量
myip=192.168.1.1 && echo $myip
myip=192.168.1.1 && echo ${myip}
myip="192.168.1.1" && echo ${myip}qq
myip="192.168.1.1" && echo '${myip}qq'
myip="192.168.1.1" && echo "${myip}qq"
path=`pwd`
path=$(pwd)
FZS_PATH=/data/fzs
cp -a ${FZS_PATH}/save/1/powerfile ${FZS_PATH}/save/1/powerfile.`date | tr " :" "-"`
变量名是由数字,字母,下划线组成,不能有其它字符,数字不能作为变量的开头
单引号原样输出,双引号解析变量,这是最基本的判断,不过由于shell脚本的书写方式非常灵活,有些时候各种单双引号互相嵌套很容易搞懵,尤其再碰到想再三剑客命令里使用shell的变量,更是复杂了,此时多注意用bash -x name.sh
的方式,仔细调试,总是可以搞定的
关键词:环境变量 系统变量 CentOS 全局变量 局部变量 Linux
1 如何创建环境变量 ?
===============================
[root@xingyongsheng ~]# cat /etc/profile | grep export
export HISTCONTROL=ignoreboth
export HISTCONTROL=ignoredups
如上,可以看到,在定义变量的时候前面加上 export 即可,通常习惯上使用大写字母定义环境变量,还可以使用declare命令来定义环境变量
declare -x NAME=hello
2 环境变量的有效范围 ?
===============================
普通变量是只在当前脚本内生效,而环境变量会在全局范围内都生效,所有的脚本都可以使用系统的环境变量
3 常见的系统环境变量配置文件有哪些 ?
===============================
/etc/profile
/etc/bashrc
~/.bash_profile
~/.bashrc
/etc/profile.d/
若要在登录后初始化或显示加载内容,则把脚本文件放在/etc/profile.d/下即可(无须加执行权限)
4 如何查看系统里有哪些环境变量 ?
===============================
set 输出所有变量,包括局部变量和全局变量
env 只显示全局变量 OR printenv
declare 输出所有的变量、函数、整数和已经导出的变量
set -o 显示bash shell所有参数的配置信息
5 常见的系统环境变量含义
===============================
HISTFILE 命令记录记录历史文件的全路径
HISTFILESIZE 历史命令文件记录的最大行数
HOME 当前用户的家目录
HOSTNAME 当前主机名称
IFS 内部字段分隔符
LANG 字符集
MAIL 邮件路径
PATH 命令执行路径
SHELL 当前使用的SHELL
6 如何引用另一个脚本里定义的变量
source commonEnv.sh
===============================
https://blog.csdn.net/xys2015/article/details/112312796
function hello() {
date
echo "hello"
}
hello
上面的函数我们直接在命令中敲击后面即可直接用 hello ,相当于自定义一个函数当命令用, 如果我们想让其重启也能生效,可以放到 /etc/profile.d/
那么问题来了,如果我们全新拿到一台机器,如何知道这台机器上有哪些函数可以用呢 ?
使用 env | grep hello 是不行的,可以使用
type hello
typeset (列出全部变量和函数)
======================= 冗余输出参考 =======================
[root@node3 ~]# type hello
hello is a function
hello ()
{
date;
echo "hello"
}
$1 $2 $3 ... ${10} ${11}
$0
$#
$*
$@
################ $1 $2 $3 ... ${10} ${11} 实践 #######################
$ cat hello.sh
echo $1 $2
(( sum=$1+$2 ))
echo $sum
$ bash hello.sh 2 5
2 5
7
############### $0 dirname basename 实践 #################################
$ cat /home/dc2-user/dir/child/hello.sh
echo $0
$ cd /home/dc2-user/dir/child && bash hello.sh
hello.sh
$ cd /home
$ bash ./dc2-user/dir/child/hello.sh
./dc2-user/dir/child/hello.sh
$ bash dc2-user/dir/child/hello.sh
dc2-user/dir/child/hello.sh
通过上面的例子我们可以看到 $0 是打印当前执行脚本的全路径,输出的结果与我们如何表示文件路径的方式有关(绝对路径 相对路径 等)
如果我们想要单独拿到执行的目录或者文件名的部分,就需要用到 dirname 和 basename
$ dirname /home/dc2-user/dir/child/hello.sh
/home/dc2-user/dir/child
$ basename /home/dc2-user/dir/child/hello.sh
hello.sh
$ cd /home && basename dc2-user/dir/child/hello.sh
hello.sh
$ cd /home && dirname dc2-user/dir/child/hello.sh
dc2-user/dir/child
############################# $# 位置参数实践 ###################################
$ cat q.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
echo $#
$ bash q.sh {1..20}
1 2 3 4 5 6 7 8 9 10 11
20
可以看到 $# 是用来确定实际传入脚本的参数个数,比如某些时候我们写的脚本要求必须传入2个参数,不能多不能少,我们就可以利用这个 $# 来实现,如下
$ cat q2.sh
if [ $# -ne 2 ]; then
echo "USAGE: /bin/bash $0 arg1 arg2"
echo "参数必须是两个"
exit
fi
echo "bula bula bula"
$ bash q2.sh
USAGE: /bin/bash q2.sh arg1 arg2
参数必须是两个
$ bash ~/q2.sh
USAGE: /bin/bash /home/dc2-user/q2.sh arg1 arg2
参数必须是两个
https://blog.csdn.net/xys2015/article/details/112575912
$? 上一次执行命令的返回值,0表示成功,非0表示失败
$$ 获取当前执行的shell脚本的进程PID
$! 获取上一个在后台工作的进程PID
$_ 获取在此之前执行的命令或脚本的最后一个参数
可用过 man bash ,搜索 Special Parameters 找到相关帮助
########################### $? 实践 #####################################
这个特殊变量是比较常用的,比如我们想要在脚本中确认,当前机器是否能上网
$ ping -c 3 -i 1 baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=54 time=4.13 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=2 ttl=54 time=3.94 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=3 ttl=54 time=2.69 ms
--- baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 4211ms
rtt min/avg/max/mdev = 2.699/3.595/4.139/0.638 ms
$ echo $?
0
$ if [ $? -eq 0 ]; then
echo "可以上网"
else
echo "不能上网"
fi
下面的测试是测试当前机器是否能连通192.168.1.232,通过 $? 输出是1,判断当前机器不能连通192.168.1.232
$ ping -c 3 -i 1 192.168.1.232
PING 192.168.1.232 (192.168.1.232) 56(84) bytes of data.
--- 192.168.1.232 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 1999ms
$ echo $?
1
########################### $$ 实践 #####################################
有时我们有这样的需求,我们写的脚本是需要在后台一直运行的,比如搭建个基于WEB界面的文件上传服务器,给大家上传下载文件用,这种类型的脚本满足两个特征
1 需要放到后台一直执行 (配合 nohuo & 实现)
2 可能需要经常重启,也就是这个脚本会多次反复执行 (这里我们就要自己保证每次执行前kill掉上一次运行的进程)
这种时候我们可以在运行这个脚本的时候尽量使用绝对路径,这样后面过滤进程PID的时候不会造成困然,另外一种比较方便的方法,就是利用 $$
[dc2-user@10-255-20-218 ~]$ cat hello.sh
echo $$
sleep 300
[dc2-user@10-255-20-218 ~]$ nohup bash hello.sh &> /tmp/tmp.out &
[1] 23512
[dc2-user@10-255-20-218 ~]$ ps -ef | grep 23512
dc2-user 23512 19141 0 11:00 pts/0 00:00:00 bash hello.sh
dc2-user 23513 23512 0 11:00 pts/0 00:00:00 sleep 300
dc2-user 23531 19141 0 11:00 pts/0 00:00:00 grep --color=auto 23512
[dc2-user@10-255-20-218 ~]$ ps -ef | head -1
UID PID PPID C STIME TTY TIME CMD
如 echo export 这样的命令是BASH SHELL自带的,这样的命令我们一般用 help echo 的方式查看其帮助,可通过 man help 查看这一类的命令
echo 输出内容
eval args 当shell程序执行到eval语句时,shell读入参数args,并将它们组合成一个新的命令,然后执行
exec args 命令能够在不创建新的子进程的前提下,转去执行指定的命令,当指定的命令执行完毕后,该进程(也就是最初的shell)就终止了,如下的方式实现了按行读取文件并处理
seq 5 > /tmp/tmp.log
cat exec.sh
exec < /tmp/tmp.log
while read line; do
echo "$line XXX"
done
上面这个exec的骚操作到底有没有实际场景呢?给大家分享一个我在实际工作中遇到的一个问题,有一个文本文件里面的内容时不断增加的,我需要对每新增的一行做处理
read 从标准输入读取字符串等信息,传给shell程序内部定义的变量
shift shift语句会按如下方式重新命名所有的位置参数变量,即$2成为$1、$3成为$2等,以此类推,在程序中每使用一次shift语句,都会使所有的位置参数依次向左移动一个位置,并使位置参数$#减1,直到减到0为止
exit exit the shell
[dc2-user@10-255-20-218 ~]$ time free
total used free shared buff/cache available
Mem: 1882212 168296 1120616 41448 593300 1495132
Swap: 0 0 0
real 0m0.009s
user 0m0.002s
sys 0m0.006s
[dc2-user@10-255-20-218 ~]$ time df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 1.9G 39G 5% /
devtmpfs 897M 0 897M 0% /dev
tmpfs 920M 0 920M 0% /dev/shm
tmpfs 920M 41M 879M 5% /run
tmpfs 920M 0 920M 0% /sys/fs/cgroup
tmpfs 184M 0 184M 0% /run/user/0
tmpfs 184M 0 184M 0% /run/user/1000
real 0m0.007s
user 0m0.003s
sys 0m0.002s
man bash 搜索 Parameter Expansion
Parameter Expansion
The `$' character introduces parameter expansion, command substitution, or arithmetic expansion. The parameter name or symbol to be expanded may be enclosed in braces, which are optional
but serve to protect the variable to be expanded from characters immediately following it which could be interpreted as part of the name.
When braces are used, the matching ending brace is the first `}' not escaped by a backslash or within a quoted string, and not within an embedded arithmetic expansion, command substitution,
or parameter expansion.
${parameter}
The value of parameter is substituted. The braces are required when parameter is a positional parameter with more than one digit, or when parameter is followed by a character which
is not to be interpreted as part of its name.
If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. Bash uses the value of the variable formed from the rest of parameter as the
name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion.
The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below. The exclamation point must immediately follow the left brace in order to introduce indirection.
In each of the cases below, word is subject to tilde expansion, parameter expansion, command substitution, and arithmetic expansion.
When not performing substring expansion, using the forms documented below, bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that
is unset.
${parameter:-word}
Use Default Values. If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
${parameter:=word}
Assign Default Values. If parameter is unset or null, the expansion of word is assigned to parameter. The value of parameter is then substituted. Positional parameters and special
parameters may not be assigned to in this way.
${parameter:?word}
Display Error if Null or Unset. If parameter is null or unset, the expansion of word (or a message to that effect if word is not present) is written to the standard error and the
shell, if it is not interactive, exits. Otherwise, the value of parameter is substituted.
${parameter:+word}
Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
${parameter:offset}
${parameter:offset:length}
Substring Expansion. Expands to up to length characters of parameter starting at the character specified by offset. If length is omitted, expands to the substring of parameter
starting at the character specified by offset. length and offset are arithmetic expressions (see ARITHMETIC EVALUATION below). If offset evaluates to a number less than zero, the
value is used as an offset from the end of the value of parameter. If length evaluates to a number less than zero, and parameter is not @ and not an indexed or associative array, it
is interpreted as an offset from the end of the value of parameter rather than a number of characters, and the expansion is the characters between the two offsets. If parameter is
@, the result is length positional parameters beginning at offset. If parameter is an indexed array name subscripted by @ or *, the result is the length members of the array begin‐
ning with ${parameter[offset]}. A negative offset is taken relative to one greater than the maximum index of the specified array. Substring expansion applied to an associative
array produces undefined results. Note that a negative offset must be separated from the colon by at least one space to avoid being confused with the :- expansion. Substring index‐
ing is zero-based unless the positional parameters are used, in which case the indexing starts at 1 by default. If offset is 0, and the positional parameters are used, $0 is pre‐
fixed to the list.
${!prefix*}
${!prefix@}
Names matching prefix. Expands to the names of variables whose names begin with prefix, separated by the first character of the IFS special variable. When @ is used and the expan‐
sion appears within double quotes, each variable name expands to a separate word.
${!name[@]}
${!name[*]}
List of array keys. If name is an array variable, expands to the list of array indices (keys) assigned in name. If name is not an array, expands to 0 if name is set and null other‐
wise. When @ is used and the expansion appears within double quotes, each key expands to a separate word.
${#parameter}
Parameter length. The length in characters of the value of parameter is substituted. If parameter is * or @, the value substituted is the number of positional parameters. If
parameter is an array name subscripted by * or @, the value substituted is the number of elements in the array.
${parameter#word}
${parameter##word}
Remove matching prefix pattern. The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches the beginning of the value of parameter, then the
result of the expansion is the expanded value of parameter with the shortest matching pattern (the ``#'' case) or the longest matching pattern (the ``##'' case) deleted. If parame‐
ter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted
with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.
${parameter%word}
${parameter%%word}
Remove matching suffix pattern. The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches a trailing portion of the expanded value of parame‐
ter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the ``%'' case) or the longest matching pattern (the ``%%'' case)
deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array
variable subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.
${parameter/pattern/string}
Pattern substitution. The pattern is expanded to produce a pattern just as in pathname expansion. Parameter is expanded and the longest match of pattern against its value is
replaced with string. If pattern begins with /, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with #, it must match
at the beginning of the expanded value of parameter. If pattern begins with %, it must match at the end of the expanded value of parameter. If string is null, matches of pattern
are deleted and the / following pattern may be omitted. If parameter is @ or *, the substitution operation is applied to each positional parameter in turn, and the expansion is the
resultant list. If parameter is an array variable subscripted with @ or *, the substitution operation is applied to each member of the array in turn, and the expansion is the resul‐
tant list.
${parameter^pattern}
${parameter^^pattern}
${parameter,pattern}
${parameter,,pattern}
Case modification. This expansion modifies the case of alphabetic characters in parameter. The pattern is expanded to produce a pattern just as in pathname expansion. The ^ opera‐
tor converts lowercase letters matching pattern to uppercase; the , operator converts matching uppercase letters to lowercase. The ^^ and ,, expansions convert each matched charac‐
ter in the expanded value; the ^ and , expansions match and convert only the first character in the expanded value. If pattern is omitted, it is treated like a ?, which matches
every character. If parameter is @ or *, the case modification operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is
an array variable subscripted with @ or *, the case modification operation is applied to each member of the array in turn, and the expansion is the resultant list.