==========================================
或者也可以在$HOME/.bashrc中添加属于自己的变量
管理文件系统
1、ext文件系统(扩展文件系统)
2、ext2文件系统(ext的升级)
3、日志文件系统
1)ext3文件系统,linux的默认文件系统
2)ext4文件系统,已经被很多发行版本的linux支持
3)Reiser文件系统,linux上最快的文件系统
4)JFS文件系统,古老的文件系统
5)XFS另外一个日志文件系统
必须先在存储设备上创建分区来容纳文件系统。分区可以是整个硬盘,也可以是硬盘的一部分,来容纳虚拟目录的一部分
fdisk是一个用来帮助管理分区的工具,他是一个交互式的命令,有下面的一些选项:
a 设置一个标志,说明这个分区是可以启动的
b 编辑BSD Unix系统用的磁盘标签
c 设置DOS兼容标志
d 删除分区
l 显示可用的分区类型
m 显示命令选项
n 增加一个新分区
o 创建DOS分区表
p 显示当前分区表
q 退出,不保存更改
s 为Sun Unix系统创建一个新的磁盘标签
t 修改分区的系统id
u 改变使用的存储单位
v 验证分区表
w 将分区表写入磁盘
x 高级功能
创建完分区就要在分区上创建文件系统,常用的工具:
mkfs.ext3 创建一个ext3文件系统
mkfs.ext4 创建一个ext4文件系统
为分区创建了文件系统之后,下一步将它挂载到虚拟目录下的某个挂载点,这样就可以将数据存储到新的文件系统中了。可以用mkdir在虚拟目录中创建一个挂载点,然后使用mount将新的文件系统挂载到这个挂载点上
fsck命令用来检查和修复任意类型的linux文件系统,格式为fsck options filesystem,常用的命令行选项如下:
-a 如果检测到错误,自动修复文件系统
-A 检查/etc/fstab文件中列出的所有文件系统
-C 给支持进度条的文件系统显示一个进度条
-N 不进行检查,只显示那些检查会执行
-r 出现错误时提示
-R 使用-A选项时跳过根文件系统
-s 检查多个文件系统时一次进行检查
-t 指定要检查的文件系统
-T 启动时不显示头信息
-V 在检查时产生详细输出
-y 检测到错误时自动修复文件系统
在现实当中,我们需要将另外一个硬盘上的分区加到已有文件系统,来动态地向已有的我呢旧系统添加空间——这个时候我们需要LVM(linux逻辑卷管理器)
逻辑卷管理的核心是它如何处理安装在系统上的硬盘分区。
在逻辑卷的世界里,硬盘被称为物理卷(PV)。每一个物理卷都会被映射到硬盘上创建的某一物理分区。
多个物理卷集中在一起可以组成一个卷组(VG)。逻辑卷管理系统会把卷组当作物理硬盘一样对待,但是事实上卷组可以由分布在多个物理硬盘上的多个物理分区组成。
卷组提供了一个创建逻辑分区的平台,而这些逻辑分区事实上包含了文件系统
整个结构最后的一层是逻辑卷(LV)。逻辑卷为linux提供了创建文件系统的分区环境。linux将逻辑卷当作物理分区对待。可以使用任意一种标准的linux文件系统来格式化逻辑卷,然后再将它在某个挂载点添加进linux虚拟目录中
在上图中,卷组横跨了三个物理硬盘,覆盖了5个独立的物理分区。在卷组上有两个独立的逻辑卷。linux将每个逻辑卷当作物理分区,每个逻辑卷可以被格式化成ext4文件系统,然后挂载到某个点上。
未使用的分区或者新增的硬盘可以被添加到存在逻辑卷上。
在linux上使用LVM:
第一步:定义物理卷
1、使用fdisk命令创建物理分区
2、通过t选项来改变分区的类型
3、用分区来创建真实的物理卷,可以使用pvcreate命令
第二步:创建卷组
1、使用vgcreate命令来创建卷组
第三步:创建逻辑卷,使用lvcreate命令,有下面的一些选项:
-c 指定快照逻辑卷的单位大小
-C 设置或重置连续分配策略
-i 指定条带数
-I 指定每条条带的大小
-l 指定分配给新逻辑卷的逻辑块数
-L 指定分配给新逻辑卷的硬盘大小
-m 创建设备的镜像数
-M 让次设备号一直有效
-n 指定新逻辑卷的名称
-p 为逻辑卷设置读写权限
-r 设置预读扇区数
-R 指定将镜像分成多大的区
-s 创建镜像逻辑卷
-Z 设置在新逻辑卷的前1KB数据为0
第四步:创建文件系统
安装软件程序
包管理系统:PMS
PMS利用数据来记录:
1、linux上已经安装了什么软件
2、每个包安装了什么文件
3、每个已安装软件包的版本
基于Debian的发行版,例如ubuntu等,使用的基础命令是dpkg
基于Red Hat的发行版,如Fedora等,使用的基础命令是rpm
基于Debian的系统,dpkg命令是核心,包含在这个PMS中的其他工具有:
apt-get
apt-cache
aptitude
使用aptitude命令可以帮助你避免常见的软件安装问题,如软件依赖关系缺失。aptitude有个很方便的交互式界面。
Aptitude show packname 快速显示包的信息
dpkg -L packname 可以查看某个包的关联的所有文件的列表
dpkg -search 绝对路径 可以查看某个文件属于哪个软件包
aptitude search packname 查找将要安装的某个包
aptitude install packname 安装软件
aptitude safe-upgrade 安全的更新所有包
aptitude remove packname 删除软件包但是不删除数据和配置文件
aptitude purge packname 删除软件包和数据以及配置文件
从源文件进行安装的步骤:
1、首先执行源文件根目录下的configure命令
2、然后进行make
3、make install
使用编辑器
vim编辑器
有两种模式:插入模式(编辑模式),普通模式(命令模式)
进入vim的时候是命令模式,按下i之后进入编辑模式,按下esc之后回到命令模式
一些常用的vim命令:
h:左移一个字符
j:下移一行
k: 上移一行
l:左移一个字符
pagedown(ctrl+F):下翻一屏
pageup(ctrl+B):上翻一屏
G:移到缓冲区的最后一行
num G:移到缓冲区的第num行
gg:移到缓冲区第一行
q!:不保存退出
wq:保存退出
w filename:保存为filename
x:删除当前光标所在位置的字符
dd:删除光标所在行
dw:删除当前(即光标处)单词
d$:删除当前至行尾的内容
J:删除当前行的换行符
u:撤销命令
a:在当前位置之后添加数据
A:在当前行的行尾添加数据
r char:用char替换当前单词
R text 用text替换当前位置的数据,直到按下esc
复制和粘贴:
在命令模式下按下v,然后上下移动即可选择文本,然后按下y旧复制了文件内容
按下p将复制的内容粘贴到当前光标处
查找和替换:
在命令模式下按下/,然后输入单词,即可进行查找,按n跳到下一个查找单词处
在命令模式下按下:/s/old/new/g或:$s/old/new/g来替换所有单词
构建基础脚本
echo $var == echo “$var” != echo '$var'
echo -n $var 不换行输出
反引号(注意不是单引号,是小键盘1(!)旁边的那个健)用于引用命令,执行命令之后获取到命令的返回值,如:
strime=`date`
重定向输出符号> ,重定向是将一个命令的输出发送到一个文件中
追加符号>>,将命令的输出追加到一个文件中
重定向输入符号<,将文件内容作为某个命令的输入
管道|,将某一个命令的输出作为一个命令的输入
使用方括号来计算数学表达式:
var=$[5 + 1]
var=$[$var1+1]
但是方括号只能计算整数不能计算浮点数,要计算浮点数需要使用bc命令,常用的使用方法:
var=`echo “scale=5; 4 / 5” | bc`
上面的语句是将计算4/5,保留位数为4,如果不舍值scale,那么将按照整数计算,加入echo的目的是将bc的计算结果输出到变量var中
或者也可以这样:
var2=`bc << EOF
scale=4
4*5.6
EOF`
效果是一样的
$?保存了上个脚本(或命令)的退出码
使用结构化命名
if command; then
command
elif command
command
elif command
command
else
command
fi
在方括号中进行条件判断,方括号即结构化判断语句(if,while、for)的test命令
数值比较(建议使用字母类型的比较符,即前面的):
-eq 是否相等 (可以使用==)
-ge 大于等于
-gt 大于(可以使用>)
-le 小于等于
-lt 小于(可以使用<)
-ne 不等于(可以使用!=)
注意test命令不能处理浮点型
字符串比较:
= 是否相同
!= 是否不同
< 小于
\> 大于(在shenll中不能直接使用>,这会被当成重定向符号,因此需要转义字符)
-n 长度是否不为0
-z 长度是否为0
文件比较:
-d file 是否存在且为一个目录
-e file 是否存在
-f file 是否存在且为一个文件
-r file 是否存在并可读
-s file 是否存在且非空
-w file 是否存在且可写
-x file 是否存在且可执行
-O file 是否存在并且是否属于当前用户
-G file 是否存在并检查默认组是否和当前用户相同
file1 -nt file2 file1是否比file2新
file1 -ot file2 file1是否比file2旧
复合条件测试:
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
由于test命令(即方括号)只能进行简单的算数操作,因此出现了双括号命令用于较复杂的算数操作
((exp)),在双括号中可以使用下面命令:
var++
var--
++var
--var
!
~
** 幂运算
<< 左偏移
>> 右偏移
&
|
&&
||
针对字符串的高级操作
[[ exp ]],可以使用模式匹配,而且大于号也不用转义
case语句:
case $var in
p1) command1;;
p2) command2;;
p3|p4) command3;;
*) default command4;;
esac
for循环的用法:
1、读取列表的值。典型用法如下:
for var in I "don't" know if "this'll" work
do
echo $var
done
其中列表有些技巧:
list=”i am mobinsheng ”
list=$list” name” #往列表中添加值
2、循环。典型用法如下:
for ((i=0;i < 10;++i))
do
echo $i
done
3、遍历目录下的文件
for v in /var/*
do
if [ -d "$v" ];then
echo $v " is Dir"
elif [ -f "$v" ];then
echo $v " is file"
#echo $v
fi
done
字段分隔符:
shell中默认的字段分隔符是空格、制表符、换行符。如果你需要自己的字段分割符号,那么要像下面这样:(把@作为分隔符)
var=$IFS
IFS=$"@"
for var in I@"don't"@know@if@"this'll"@work
do
echo $var
done
IFS=$var
while循环。常见的结构如下:
var=1
while [ $var -lt 10 ];
do
echo $var
var=$[$var+1];
done
until循环。常见用法:
var=1
until [ $var -eq 10 ];
do
echo $var;
var=$[$var+1];
done
在循环中可以使用break和continue命令(可以指定跳过的循环层数)
用户输入
位置参数:
$0表示脚本名字
$1表示第一个参数
。。。
$9表示第九个参数
${10}第十个参数
使用位置参数之前先测试相应的位置参数是否有数据,一般使用if [ -n “$1” ]
$# 表示参数的个数
$@ 表示单词的列表,可以使用for进行遍历
$* 把多有单词当作一个单词
shift命令会移动命令参数,每执行一次,所有参数就会左移一个位置$2变成$1,以此类推
处理选项:
简单的选项:
while [ -n "$1" ]
do
case "$1" in
-a) echo "option a";;
-b) echo "option b";;
*) ;;
esac
shift
done
复杂的带参数的选项:
set -- `getopt -q ab:c "$@"`
while [ -n "$1" ]
do
case "$1" in
-a) echo "option a";;
-b) echo "option b" " value = $2";;
-c) echo "option c";;
*) ;;
esac
shift
done
set -- `getopt -q ab:c "$@"`详解:-q表示忽略一些用户输入的不存在的选项,ab:c表示有三个选项,其中b选项带参数,$@表示原始的输入参数,它会被getopt命令格式化
另外一个更牛的处理选项的方式(注意case判断中选项没有破折号):
while getopts :ab:c opt
do
case "$opt" in
a) echo "option a";;
b) echo "option b" " value = $OPTARG";;
c) echo "option c";;
*) ;;
esac
done
getopts处理每一个选项的时候,会将环境变量OPTIND的值加1。getopts处理完成之后,可以使用shift命令和OPTIND一起来移动参数
shift $[ $OPTIND – 1 ]
read命令从标准输入或者另一个文件描述符读取输入:
read name 或 read -p “please enter your name:” name
可以用-t选项指定read的等待超时的时间
读取密码的时候可以指定-s选项(隐藏方式读取)
使用read读取文本(将cat之后的输出用管道传给带while的read):
count=1
cat 1.sh | while read line
do
echo "line$count:$line"
count=$[ $count+1 ]
done
呈现数据
标准输入:STDID = 0
标准输出:STDOUT = 1
标准错误:STDERR = 2
在脚本中如果需要重定向输出到某一个文件而不是输出,可以使用exec。
例如:
exec 1>text
echo "mobinsheng"
echo "hello world"
同理重回定向错误输出也可以使用exec 2>filename
重定向输入:exec 0<filename
例如:
exec 0<text
count=1
while read line
do
echo "line$count:$line"
count=$[ $count+1 ]
done
shell脚本中最多可以打开9个文件描述符,除了0~2分配给了标准输入、输出、错误之外,3~8都没有被分配。所以可以将这些文件描述符分配给任意一个文件(使用exec),例如:
exec 3>text2
echo "sssssssssssss" >&3
也可以将exec命令来将输出追加到现有文件中,而不是创建一个新文件:exec 3>>text2
把重定向的文件描述符恢复:
exec 3>&1 #将3指向标准输出流,即3保存了标准输出
exec 1>text # 将标准输出重定向到text中
。。。
exec 1>&3 # 恢复
对于已经重定向的输入,同理:
exec 0<&4 #用4保存标准输入
exec text<0 #把标准输入重定向到text中
….
exec 4<&1 #恢复
关闭文件描述符:
exec 3>text #把3重定向到text中
exec 3>&- #关闭文件描述符3
有时你不想显示脚本的输出,这在将脚本作为后台进程执行时很常见。此时可以把输入或者错误重定向到/dev/null
还可以将/dev/null作为输入,这样可以快速删除一个文件的内容,但是文件仍然存在,只是变空了
创建临时文件:
mktemp text.XXXXXX 可以创建出类似于text.326541这样的文件,常见用法:
filename=`mktemp text.XXXXXX`
mktemp的-t选项会强制命令在系统的临时目录中创建临时文件
mktemp的-d选项会创建临时文件夹
分流器tee,可以一边将输出显示在屏幕上一边将输出导入日志中,常见用法:date|tee filename
tee的-a选项是追加到文件末尾,这样就不会覆盖原文件的内容了
控制脚本
信号
常用的信号:
SIGHUP 挂起进程
SIGINT 终止进程
SIGQUIT 停止进程
SIGKILL 无条件终止进程
SIGTERM 可能的话终止进程
SIGSTOP 无条件停止进程,但是不会终止进程
SIGTSTP 停止或暂停进程,但不终止进程
SIGCONT 继续运行停止的进程
ctrl+c 会终止jincheng
ctrl+z 会暂停进程
在脚本中可以使用trap来捕捉信号,格式是:trap commad signals,例如:
trap "echo ;echo get ctrl+c" SIGINT
sleep 1000
或者:
function handle()
{
echo ;
echo "get ctrl+c"
}
trap handle SIGINT
sleep 1000
在脚本退出时执行某个命令(例如清理等工作),可以用trap实现,例如:
trap "echo bybe" EXIT
可以用单破折线作为命令,后跟要移除的信号来移除一组信号捕捉,将其恢复到正常状态,例如:
trap – EXIT
脚本名& 这样可以实现脚本在后台运行。但是此时如果你退出控制台的话,进程还是会被终止,如果想要在退出终端后进程继续运行,那么需要nohup命令:
nohup ./test.sh &
定时运行脚本
at命令允许指定系统何时运行脚本:
at -f filename time
at -f ./test.sh 14:39
atq 命令可以列出等待的作业(定时作业)
atrm 作业号 ——命令可以删除等待的作业
计划定期执行脚本(周期性执行脚本):
使用cron时间表
cron表的格式:
min hour dayofmonth month dayofweek command
cron表运行使用特定值、值范围(例如1~5)或者是通配符(星号)来指定条目。加入你要在每天的10:15运行一个命令,可以这样指定:
15 10 * * * command
首先使用crontab -l查看用户是否有crontab
使用crontab -e为cron表添加一条记录
如果你的脚本不需要有精确的执行时间,用预配置的cron脚本目录会更方便,有四个基本的目录:
/etc/cron.daily
/etc/cron.hourly
/etc/cron.monthly
/etc/cron.weekly
把自己的脚本复制到相应目录下
设置启动时运行(有几个方法):
1、在本地开机文件位置添加自己的需要开机运行的脚本:
debian /etc/init.d/rc.local
Fedora /etc/rc.d/rc.local
Ubuntu /etc/rc.local
2、在主目录的.bash_profile中添加命令或者脚本
3、在主目录的.bashrc中添加命令或脚本
创建函数
函数的典型样子:
function printName()
{
echo "mbs"
}
或
printName()
{
echo "mbs"
}
调用函数:
printName; #注意调用函数的时候不能加括号
注意不要覆盖原先定义的函数名
默认情况下,函数的退出码是函数中最后一条命令返回的退出状态码。在函数执行之后,可以使用#?来查看函数的退出码是什么
可以使用return来退出函数并返回退出码
注意!!!!!
函数中return返回的是函数的退出码,并不是函数的返回值(例如计算两个相加的函数,不能通过return返回计算值),相反,在函数中要返回一个值,需要用echo语句,例如:
function calX()
{
i=10;
echo $[ $i * 2 ];
}
var=`calX`;
echo $var
shell将函数当作小型脚本来处理。因此可以向函数传递参数,例子:
function calX()
{
echo $1
i=10;
echo $[ $i * 2 ];
}
var=`calX 1010 122`; #调用函数,并传递函数
注意函数中的参数$1等和脚本主体的参数是不一样的,所以不哟个担心会混淆,在函数中使用脚本主体的参数需要传递给函数
函数会用到两种类型的变量:全局变量、局部变量。
默认情况下,脚本中的任何变量都是全局变量
如果不想造成混乱可以使用局部变量,局部变量:local var=123
数组变量:
定义数组:array=(1 2 3 4 5)
向函数中传递数组的方法:
function pt()
{
local var=(`echo "$@"`)
echo ${var[*]}
}
array=(1 2 3 4 5)
pt ${array[*]}
从函数中返回数组:
function retA()
{
local a=(1 5 6)
echo ${a[*]}
}
var=`retA`
echo ${var[*]}
由于函数局部变量的出现,因此函数可以自成体系。由此,函数可以递归调用,也可以做成模块.
模块的做法:
在2.sh(模块或者库)中定义如下函数:
#!/bin/bash
function TestBlock()
{
echo "hello"
}
在其他脚本中调用
. ./2.sh #前面一个点是资源加载符号,后面一个点和/连起来表示2.sh在当前路径下,即lib_path
var=`TestBlock` #调用库的函数
echo $var
可以在.bashrc文件中定义函数,这样就可以方便使用
在脚本中,默认的变量值都是字符串,如果你想定义非字符串的变量,可以使用declare,如下
declare [-afirx] var=xxxx
参数说明:
-a 定义为数组
-f 定义为函数
-i 定义为整数
-r 定义为只读
-x 定义为通过环境输出变量
调试脚本:
sh [-nvx] scripts
-n 不执行脚本,查询脚本内的语法,若有错误则列出
-v 在执行脚本之前,先将脚本的内容输出到屏幕
-x 和-v类似,但是稍微有点不同
配置用户之前建议先安装Linuxconf