1:shell是什么
Shell是用户与Linux操作系统沟通的桥梁
Linux的Shell种类众多,这里我们学习的是bash,也就是Bourne Again Shell
1:由于易用和免费,Bash在日常工作中被广泛使用
2:Bash是大多数Linux系统默认的Shell。
2:shell脚本文件格式
文件名后缀通常是 .sh
#!/bin/bash
#这里是注释
在一般情况下,人们并不区分Bourne Shell 和Bourne Again Shell,所以,在这里,我们可能看到#!/bin/bash,它同样也可以改为#!/bin/sh。
3:脚本执行的常用方式
a.sh
这样的话需要保证脚本具有执行权限并且在环境变量PATH中有(.),这样在执行的时候会先从当前目录查找
./a.sh
只要保证这个脚本具有执行权限即可
/usr/local/a.sh
只要保证这个脚本具有执行权限即可
bash a.sh
直接可以执行,甚至这个脚本文件中的第一行都可以不引入
bash的单步执行
bash -x /path/to/aa.sh
bash的语法检查
bash -n /path/to/aa.sh
4:变量分类
(1)本地变量
只对当前shell进程有效的,对当前进程的子进程和其它shell进程无效。
定义:VAR_NAME=VALUE
变量引用:${VAR_NAME}
取消变量:unset VAR_NAME
相当于java中的私有变量,只能对当前类使用,子类和其它类都无法使用。
(2)环境变量
自定义的环境变量对当前shell进程及其子shell进程有效,对其它shell进程无效
定义:export VAR_NAME=VALUE
对所有shell进程否有效需要配置到配置文件中
vi /etc/profile
source /etc/profile
相对于java中的protected修饰符,对当前类,子孙类,以及同一个包下面的可以共用。
和windows中的环境变量类似
(3)局部变量
在函数中调用,函数执行结束,变量就会消失
对shell脚本代码中某代码片段有效
定义:local VAR_NAME=VALUE
相当于java代码中的某一个方法中定义的局部变量,只对这个方法有效
(4)位置变量
$1,$2,.....${10}....
test.sh 3 89
$0:脚本自身
$1:脚本的第一个参数
$2:脚本的第二个参数
相当于java中main函数中的args参数,可以获取外部参数
(5)特殊变量
$?:接收上一条命令的返回状态码
返回状态在0~255之间
$#:参数个数
$*:或者$@:所有的参数
$$:获取当前shell的进程号(PID)(可以实现脚本自杀)(或者使用exit命令直接退出,也可以使用exit[num])
5:单引号、双引号、反引号
单引号不解析变量
echo '$crxy'
双引号会解析变量
echo "$crxy"
反引号是执行并引用一个命令的执行结果。类似于$(...)
echo `$crxy`
6:for循环
通过使用一个变量去遍历给定列表中的每个元素,在每次变量赋值时执行一次循环体,直至赋值完成所有元素退出循环
格式1:
for ((i=0;i<10;i++))
do
...
done
格式2:
for i in 0 1 2 3 4 5 6 7 8 9
do
...
done
格式3:
for i in {0..9}
do
...
done
注意:for i in {0..9}等于for i in {0..9..1}
7:条件测试
bash条件测试
格式:
test EXPR
[ EXPR ]:注意中括号和表达式之间的空格
整形测试:
-gt :大于:例如[ $num1 -gt $num2 ]或者test $num1 -gt $num2
-lt:小于
-ge:大于等于
-le:小于等于
-eq:等于
-ne:不等于
字符串测试
=:等于,例如判断变量是否为空 [ "$str" = "" ] 或者[ -z $str ]
!=:不等于
8:while循环
适用于循环次数未知,或不便用for直接生成较大的列表是时
格式:
while测试条件;do
循环体
done
如果测试条件为“真”,则进入循环,测试条件为“假”,则退出循环。
9:if判断
单分支:
if 测试条件;then
选择分支
fi
双分支:
if 测试条件
then
选择分支1
else
选择分支2
fi
多分支:
if 条件1; then
分支1
elif 条件2; then
分支2
elif 条件3; then
分支3
...
else
分支n
fi
10:case判断
有多个测试条件时,case语句会使得语法结构更清晰
格式:
case 变量引用 in
PATTERN1)
分支1
;;
PATTERN2)
分支2
;;
...
*)
分支n
;;
esac
PATTAERN:类同于文件名通配机制,但支持使用|表示或者
a|b:a或者b
*:匹配任意长度的任意字符
?:匹配任意单个字符
[a-z]:指定范围内的任意单个字符
11:循环控制命令-break
break命令时在处理过程中跳出循环的一种简单方法,可以使用break命令退出任何类型的循环,包括while循环和for循环
12:循环控制命令-continue
continue命令是一种提前停止循环内命令,而不完全终止循环的方法,这就需要在循环内设置shell不执行命令的条件
13:算术运算符
let varName=算术表达式
varName=$[算术表达式]
varName=$((算术表达式)
varName=`expr $num1 + $num2`------使用这种格式时要注意两个数字和+号中间要有空格。
14:自定义函数
function 函数名(){
···
}
引用自定义函数文件时,使用source func.sh有利于代码的重用性
函数传递参数
函数的返回值,只能是数字
15:帮助命令
help/man
linux中的命令可以分为两种
内建命令:command is a shell builtin
外部命令:显示具体路径
如何区分命令属于哪一种
type command
内建命令使用help command
外部命令使用man command
16:date
显示当前时间
格式化输出 +%Y-%m-%d
格式%s表示自1970-01-01 00:00:00以来的秒数
指定时间输出 --date='2009-01-01 11:11:11'
指定时间输出 --date='3 days ago'
17:read
read命令接收标准输入(键盘)的输入,或者其他文件描述符的输入。得到输入后,read命令将数据放入一个标准变量中。
格式:
read VAR_NAME
read如果后面不指定变量,那么read命令会将接收到的数据放置在环境变量REPLY中
read -p "Enter your name:" VAR_NAME
read -t 5 -p "enter your name:" VAR_NAME
read -s -p "Enter your password: " pass
18:declare
用来限定变量的属性
-r 只读
-i 整数:某些算术计算允许在被声明为整数的变量中完成,而不需要特别使用expr或let来完成。
-a 数组
19:字符串操作
获取长度:${#VAR_NAME}
字符串截取
${variable:offset:length}或者${variable:offset}
取尾部的指定个数的字符
${variable: -length}------注意冒号后面有空格
大小写转换
小--->大:${variable^^}
大--->小:${variable,,}
20:数组
定义:declare -a:表示定义普通数组
特点:
支持稀疏格式
仅支持一维数组
数组赋值方式
一次对一个元素赋值:a[0]=$RANDOM
一次对多个元素赋值:a=(a b c d)
按索引进行赋值:a=([0]=a [3]=b [1]=c)
使用read命令:read -a ARRAY_NAME
查看元素
${ARRAY[index]}:查看数组指定角标的元素
${ARRAY}:查看数组的第一个元素
${ARRAY[*]}或者${ARRAY[ @]}:查看数组的所有元素
获取数组长度
${#ARRAY[*]}
${#ARRAY[@]}
获取数组内元素的长度
${#ARRAY[0]
注意:${#ARRAY[0]}表示获取数组中的第一个元素的长度,等于${#ARRAY}
从数组中获取某一片段之内的元素
格式:${ARRAY[@]:offset:length}
offset:偏移的元素个数
length:取出的元素个数
${ARRAY[@]:offset:length}:取出偏移量后的指定个数的元素
${ARRAY[@]:offset}:取出数组中偏移量后的所有元素
数组删除元素:
unset ARRAY[index]
21:后台模式运行脚本
在脚本后面加一个&
test.sh &
这样的话虽然可以在后台运行,但是当用户注销(logout)或者网络断开时,终端会收到Linux HUP信号(hangup)信号从而关闭其所有子进程
nohup命令
不挂断的运行命令,忽略所有挂断(hangup)信号
使用nohup test.sh &
nohup会忽略进程的hangup挂断信号,所以关闭当前会话窗口不会停止这个进程的执行。
nohup会在当前执行的目录生成一个nohup.out日志文件
22:标准输入、输出、错误、重定向
标准输入、输出、错误可以使用文件描述符0、1、2引用
使用重定向可以把信息重定向到其他位置
ls >file 或者 ls 1>file(ls >>file)
lk 2>file(lk是一个错误命令)
ls >file 2>&1 ls > /dev/null(把输出信息重定向到无底洞)
例子:command >/dev/null 2>&1
23:crontab定时器
linux下的定时任务
编辑使用crontab -e
一共6列,分别是:分 时 日 月 周 命令
查看使用crontab -l
删除任务crontab -r
查看crontab执行日志
tail -f /var/log/cron
必须打开rsyslog服务cron文件中才会有执行日志(service rsyslog status)
tail -f /var/spool/mail/root(查看crontab最近的执行情况)
查看cron服务状态
service crond status
启动cron服务
service crond start
24:ps和jps
ps:用来显示进程相关信息
ps------显示当前启动的所有进程
ps -a------显示系统中所有进程
ps -ef|grep java
jps:类似linux的ps命令,不同的是平时用来显示所有进程,而jps只显示java进程,准确的说是显示当前用户已启动的部分java信息,信息包括进程号和简短的command。
问题:某个java进程已经启动,用jps却显示不了该进程进程号,使用ps -ef|grep java却可以看到
java程序启动后,默认(请注意是默认)会在/tmp/hsperfdata_userName目录下以该进程的id为文件名新建文件,并在该文件总存储jvm运行的相关信息,其中的userName为当前用户的用户名,/tmp/hsperfdata_userName目录会存放该用户的所有已经启动的java进程信息。而jps、jconsole、jvisualvm等工具的数据来源就是这个文件(/tmp/hsperfdata_userName/pid)。所以当该文件不存在或是无法读取时就会出现jps无法查看该进程号。
原因:
1:磁盘读写、目录权限问题
2:临时文件丢失,被删除或是定期清理
3:java进程信息文件存储地址被设置,不在/tmp目录下
25:vi常用命令小技巧
查找字符串
/string
查找下一个,按“n”即可
查找某一行
:10(直接跳转到第10行)
复制粘贴
yy(复制当前行)
2 yy(从当前行开始,复制2行)
p(粘贴)
删除
dd(删除当前行)
跳到文件最后一行
G
26:linux-SecureCRT假死问题
ctrl+s会造成终端假死,什么都无法输入,这个命令时linux中一个比较古老的命令
ctrl+q退出假死状态