概述
前言:
本部分主要参考此博客:
https://www.w3cschool.cn/shellbook/uglqdozt.html
数值运算:
进制转换:
其他进制转换为10进制, 可以使用Shell内置的进制转换
如将8进制的11转换为10进制:
echo "8to10 $[8#11]"
直接使用bc
计算器, 能直接指定源&目标进制, 方便转换
由于bc是交互式的计算器, 所以这里没法直接使用参数的形式进行, 而是采用echo一个用分号分割的多条语句组成的字符串给bc, 其将自动打印结果
echo "obase=16;ibase=10;1024*1024" | bc
ascii字符编码:
使用od
命令, 可以实现将某些字符串以特定的进制表示
这个暂时不知道啥用, 先放着
浮点计算:
快速入门篇介绍了常规的整数计算, 但是无论是内置方法, 还是let, expr, 都无法执行浮点运算
这里需要借助bc
或 awk
实现
和上头的进制转换相同, 也是使用echo将多语句传给交互式的bc
echo "1.1+2.2" | bc
echo "1.1-2.2" | bc
echo "1.1*2.2" | bc
echo "scale=3;7/2.2" | bc
这里用到了指定精度用的scale
bc中还有其他几个内置变量, 计算时经常用到
变量名 | 作 用 |
---|---|
scale | 指定精度,也即小数点后的位数;默认为 0,也即不使用小数部分。 |
ibase | 指定输入的数字的进制,默认为十进制。 |
obase | 指定输出的数字的进制,默认为十进制。 |
last 或者 . | 表示最近打印的数字 |
注意:obase 要尽量放在 ibase 前面,因为 ibase 设置后,后面的数字都是以 ibase 的进制来换算的
高级浮点计算:
使用到bc
的几个内置函数
使用这些函数需要加-l
参数
函数名 | 作用 |
---|---|
s(x) | 计算 x 的正弦值,x 是弧度值。 |
c(x) | 计算 x 的余弦值,x 是弧度值。 |
a(x) | 计算 x 的反正切值,返回弧度值。 |
l(x) | 计算 x 的自然对数。 |
e(x) | 求 e 的 x 次方。 |
j(n, x) | 贝塞尔函数,计算从 n 到 x 的阶数。 |
复杂的计算可以使用awk
实现
随机数:
这里使用到环境变量RANDOM
, 他能产生0<=RANDOM<=32767的随机数
或者使用awk的rand()函数, 其能产生0<=rand()<=1的随机数
echo $RANDOM
随机IP地址:
defaultGatway="192.169.1.1"
# 求IP地址前缀, 用于后头的地址拼接
len=${#defaultGatway}
echo "len=${len}"
i=$[${len}-1]
while [ ${i}>=0 ]
do
temp=${i}
substr=${defaultGatway:${i}:1}
echo "substr=${substr}"
if [ ${substr}="." ]
then
echo "index=${i}"
netIndex=${defaultGatway:0:${i}}
break
fi
i=$[${i}-1]
done
echo "netIndex=${netIndex}"
rand=$RANDOM
rand=$[rand%256]
echo "rand=${rand}"
echo "rand IP address = ${netIndex}${rand}"
统计字符串中单词出现的次数
这里主要用到了sed
sed -e "s/[^a-zA-Z]/n/g" shellTest2.sh | grep -v "^$" | sort | uniq -c | sort -n -k 1 -r
[hhtxzzj@localhost temp]$ /bin/bash "/home/hhtxzzj/temp/shellTest.sh"
77 echo
22 i
20 var
20 a
18 ans
12 b
11 then
11 n
11 if
11 fi
9 else
8 file
7 v
7 rand
7 done
7 do
6 printf
6 d
6 bc
5 while
5 sh
5 s
5 defaultGatway
4 true
4 temp
4 substr
4 str
4 shellTest
4 netIndex
4 len
4 int
4 input
4 fun
3 subs
3 read
3 name
3 for
3 false
3 cos
2 sort
2 sed
2 scale
2 ret
2 r
2 passwd
2 msg
2 list
2 let
2 is
2 IP
2 Hello
2 g
2 function
2 e
2 data
2 D
2 break
1 zA
1 Z
1 your
1 x
1 wget
1 W
1 w
1 usr
1 uniq
1 to
1 THIS
1 This
1 this
1 than
1 Substring
1 sqrt
1 spider
1 source
1 rootfs
1 return
1 RANDOM
1 of
1 od
1 obase
1 net
1 N
1 mi
1 match
1 makeFiles
1 M
1 location
1 l
1 k
1 janusvsuperpc
1 index
1 in
1 ibase
1 home
1 hhtxzzj
1 head
1 grep
1 funciton
1 found
1 f
1 Enter
1 efg
1 dynv
1 cat
1 c
1 bin
1 bigger
1 BEGIN
1 bash
1 awk
1 at
1 address
1 abc
统计指定单词出现的次数:
# 判定输入参数的个数, 至少应该输入2个参数
if [ $# -lt 1 ]
then
echo "need at lest 2 args"
exit -1
fi
# 获取源文件名 & 目标单词数
file=$1
wordsNum=$#-1
# 将全体单词数统计结果暂存
# 这里如果暂存到变量中会导致缺少n
sed -e "s/[^a-zA-Z]/n/g" ${file} | grep -v "^$" | sort | uniq -c | sort -n -k 1 -r > temp.tmp
# 循环grep输出
for((i=0;i<${wordsNum};++i))
do
shift
# echo "${1}"
# echo
cat temp.tmp | grep "b${1}b"
done
布尔运算
这里主要使用test进行相关测试
test能非常方便的完成一些简单的测试, 所以进行逻辑判定时如果涉及文件等, 首选test
先看下test 的help
test: test [expr]
Evaluate conditional expression.
Exits with a status of 0 (true) or 1 (false) depending on
the evaluation of EXPR. Expressions may be unary or binary. Unary
expressions are often used to examine the status of a file. There
are string operators and numeric comparison operators as well.
The behavior of test depends on the number of arguments. Read the
bash manual page for the complete specification.
File operators:
-a FILE True if file exists.
-b FILE True if file is block special.
-c FILE True if file is character special.
-d FILE True if file is a directory.
-e FILE True if file exists.
-f FILE True if file exists and is a regular file.
-g FILE True if file is set-group-id.
-h FILE True if file is a symbolic link.
-L FILE True if file is a symbolic link.
-k FILE True if file has its `sticky' bit set.
-p FILE True if file is a named pipe.
-r FILE True if file is readable by you.
-s FILE True if file exists and is not empty.
-S FILE True if file is a socket.
-t FD True if FD is opened on a terminal.
-u FILE True if the file is set-user-id.
-w FILE True if the file is writable by you.
-x FILE True if the file is executable by you.
-O FILE True if the file is effectively owned by you.
-G FILE True if the file is effectively owned by your group.
-N FILE True if the file has been modified since it was last read.
FILE1 -nt FILE2 True if file1 is newer than file2 (according to
modification date).
FILE1 -ot FILE2 True if file1 is older than file2.
FILE1 -ef FILE2 True if file1 is a hard link to file2.
String operators:
-z STRING True if string is empty.
-n STRING
STRING True if string is not empty.
STRING1 = STRING2
True if the strings are equal.
STRING1 != STRING2
True if the strings are not equal.
STRING1 < STRING2
True if STRING1 sorts before STRING2 lexicographically.
STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.
Other operators:
-o OPTION True if the shell option OPTION is enabled.
-v VAR True if the shell variable VAR is set
! EXPR True if expr is false.
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
Arithmetic binary operators return true if ARG1 is equal, not-equal,
less-than, less-than-or-equal, greater-than, or greater-than-or-equal
than ARG2.
Exit Status:
Returns success if EXPR evaluates to true; fails if EXPR evaluates to
false or an invalid argument is given.
几个比较常用的点
test内部逻辑运算与Shell内置的逻辑运算符稍有不同:
-
-a
(and) 对应 && -
-o
(or) 对应 || -
非运算都是
!
-
在
Bash
里,test
命令可以用[] 运算符取代,但是需要注意,[
之后与]
之前需要加上额外的空格这常用在之前的流程控制语句中, 如if-else
几个简单的栗子:
要求某文件非空且可执行
两种方法
file="shellTest2.sh"
if test -s ${file} && test -x ${file}
then
echo "${file} yes"
else
echo "${file} no"
fi
if test -s ${file} -a -x ${file}
then
echo "${file} yes"
else
echo "${file} no"
fi
替换为[]
版本, 看上去更加简洁
if [ -s ${file} ] && [ -x ${file} ]
then
echo "${file} yes"
else
echo "${file} no"
fi
if [ -s ${file} -a -x ${file} ]
then
echo "${file} yes"
else
echo "${file} no"
fi
命令列表
命令列表就是使用&& || 构建逻辑判断句, 减少if-else的使用
命令列表仍然遵循逻辑运算的短路法则
- &&连接的命令, 前头的false, 后头不执行, 反之执行
- ||连接的命令, 前头true, 后头不执行, 反之执行
小栗子:
echo $#
echo $1
if [ $# -eq 1 ] && (echo $1 | grep ^[0-9]*$ >/dev/null);then
echo "YES"
fi
/dev/null为一个黑洞文件, 输出到这个文件中的内容被视为丢弃, 但报告写入成功, 读取这个文件会立刻报告一个EOF
所以以上命令的意思是, 要求输入参数的数量必须为1, 且参数为数字, 否则grep就不会向null文件写入, 也就不会返回true
使用命令列表将if-else简化
echo $#
echo $1
! ([ $# -eq 1 ] && (echo $1 | grep ^[0-9]*$ >/dev/null)) && exit 1
echo "YES"
代码更加美观, 但是设计上逻辑较为复杂
字符串操作:
这里先介绍2个特殊的文件
/dev/null
和 /dev/zero
参考博客:
https://blog.csdn.net/longerzone/article/details/12948925
/dev/null
被称之为空设备, 或黑洞, 是一个特殊的设备文件
写入其中的数据都会丢弃, 但报告写入操作成功, 读取会立刻得到一个EOF
常用于将垃圾数据重定向到黑洞中进行丢弃
/dev/zero
在读取的时候, 能无限制的提供空字符(NULL, ASCII NUL, 0x00)
常用其提供的字符流来覆盖信息, 或是产生一个特定大小的空白文件
字符串查找
字符串这里常用的查找操作是grep, grep+正则能解决绝大多数的字符串查找问题
使用要点:
grep支持正则表达式, 但是最好使用的时候都带上-E
-e
, 否则不支持完整的正则, 或部分正则字符会和grep自身的内置规则冲突, 导致需要使用转移才能正常正则
如, 查找-
开头的字符串, 没有-e
的情况下需要使用转义
判断是否为可打印字符
j="tn"
echo ${j} | grep -E -e "[[:print:]]+"
字符串显示
这里就是实现以下几个功能:
- 显示特定颜色背景的字符串
- 将字符串打印在屏幕的特定位置
用的不多, 有用到在看
参考博客:
https://www.w3cschool.cn/shellbook/6ngszozt.html
字符串存储:
字符串拆分为数组:
默认情况下, 将以空格为分隔符拆分字符串, 形成由单词组成的数组
str="get the length of me"
var_str=(${str})
for((i=0;i<5;++i))
do
echo ${var_str[${i}]}
done
或者可以使用for进行访问, 也能达到同样的效果:
str="get the length of me"
for i in ${str}
do
echo ${i}
done
还可以使用awk将字符串划分为数组, 但也是以空格划分, 并不能做到像C++一样使用下标访问每一个字符
此外, awk还支持数组下标为字符串, 即实现map映射数组
字符串的常规操作
取子串
下标直接定位
$ var="get the length of me"
$ echo ${var:0:3}
get
$ echo ${var:(-2)} # 方向相反呢
me
$ echo `expr substr "$var" 5 3` #记得把$var引起来,否则expr会因为空格而解析错误
the
$ echo $var | awk '{printf("%sn", substr($0, 9, 6))}'
length
awk` 把 `$var` 按照空格分开为多个变量,依次为 `$1`,`$2`,`$3`,`$4`,`$5`, 而$0 代表整个字符串
匹配字符求子串
bash内置规则:
$ echo ${var%% *} #从右边开始计算,删除最左边的空格右边的所有字符
get
$ echo ${var% *} #从右边开始计算,删除第一个空格右边的所有字符
get the length of
$ echo ${var##* } #从左边开始计算,删除最右边的空格左边的所有字符
me
$ echo ${var#* } #从左边开始计算,删除第一个空格左边的所有字符
the length of me
使用sed更加方便, 功能也更加强大
# 删除所有 空格+字母组合 的字符串:
$ echo $var | sed 's/ [a-z]*//g'
get
$ echo $var | sed 's/[a-z]* //g'
me
tr通常用来替换部分字符, 也能实现子串截取
head
& tail
可实现取首尾部分
查询子串
子串查询包括:
- 返回符合某个模式的子串本身
- 返回子串在目标串中的位置
expr index 可以实现返回某个字符或多个字符中第一个字符出现的位置
$ var="get the length of me"
$ expr index "$var" t
3
而awk脚本可以实现更为复杂的功能, 如找出子串, 以及使用match匹配正则表达式
$ echo $var | awk '{printf("%dn", match($0,"the"));}'
5
所以推荐直接使用awk
awk
中内置的使用正则表达式的函数:
# 替换正则匹配的第一个串, 返回替换的数量
sub( Ere, Repl, [ In ] )
# Ere 正则
# Repl 替换串
# In 源串
# 替换正则匹配的所有串, 其余与stb() 相同
gsub( Ere, Repl, [ In ] )
# 参数与sub() 相同
# 返回正则匹配的串的起始下标(index从1开始), 如果没找到, 返回0
match( String, Ere )
# String 源串
# Ere 正则
# 将String分割为字符串数组, 存储在a中
split( String, A, [Ere] )
# String 源串
# A 目标字符串数组
# Ere 正则指定的分隔符
其他几个都很好理解, 这里来尝试一下split
str="W123D43N54M654D"
out=`echo ${str} | awk '{split($0, a, "[0-9]+"); print a[1],a[2],a[3],a[4],a[5]}'`
echo ${out}
子串替换
shell仍然内置了子串替换功能, 不过用的不经常
$ var="get the length of me"
$ echo ${var/ /_} #把第一个空格替换成下划线
get_the length of me
$ echo ${var// /_} #把所有空格都替换成下划线
get_the_length_of_me
通常直接使用sed
或 awk
进行子串替换
$ echo $var | awk '{sub(" ", "_", $0); printf("%sn", $0);}'
get_the length of me
$ echo $var | awk '{gsub(" ", "_", $0); printf("%sn", $0);}'
get_the_length_of_me
$ echo $var | sed -e 's/ /_/' #s <= substitude
get_the length of me
$ echo $var | sed -e 's/ /_/g' #看到没有,简短两个命令就实现了最小匹配和最大匹配g <= global
get_the_length_of_me
插入子串
同样来看一下Shell内置功能
$ var="get the length of me"
$ echo ${var/ /_ } #在指定字符串之前插入一个字符串
get_ the length of me
$ echo ${var// /_ }
get_ the_ length_ of_ me
$ echo ${var/ / _} #在指定字符串之后插入一个字符串
get _the length of me
$ echo ${var// / _}
get _the _length _of _me
插入子串主要来看sed
$ echo $var | sed -e 's/( )/_1/'
get_ the length of me
$ echo $var | sed -e 's/( )/_1/g'
get_ the_ length_ of_ me
$ echo $var | sed -e 's/( )/1_/'
get _the length of me
$ echo $var | sed -e 's/( )/1_/g'
get _the _length _of _me
$ echo $var | sed -e 's/([a-z]*) ([a-z]*) /2 1 /g'
the get of length me
这里可以看到sed
的一个分组功能
类似于正则的分组, sed使用()
对匹配到的字符进行分组, 并能在后头使用1
, 2
灯光进行调用
这里使用()
需要用转义字符( )
这里插入字符的实现思路主要是, 使用s
替换字符, 首先定位, 在将源内容输入, 并增加插入内容
删除子串:
删除子串就是将目标子串替换为空即可
没啥好说的
子串排序:
这里主要用到sort
命令
同样, cut
与 万能的awk
也能做到
$ var="get the length of me"
$ echo $var | tr ' ' 'n' | sort #正序排
get
length
me
of
the
$ echo $var | tr ' ' 'n' | sort -r #反序排
the
of
me
length
get
可以注意到, sort排序的单位是行
所以对于如下的数值排序, 使用sort的话需要将所有的空格替换为n
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
41 45 44 44 26 44 42 20 20 38 37 25 45 45 45
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
44 20 30 39 35 38 38 28 25 30 36 20 24 32 33
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
41 33 51 39 20 20 44 37 38 39 42 40 37 50 50
46 47 48 49 50 51 52 53 54 55 56
42 43 41 42 45 42 19 39 75 17 17
cat shellTest2.sh | sed -e "s/ /n/g" | sort -k 1 -n

子串进制转换
这个在快速入门篇中讲过, 直接使用bc进行
$ echo "ibase=10;obase=16;10" | bc
A
子串编码转换
这里主要使用iconv
工具进行
iconv命令用于文件编码的转换
如在不同的操作系统中交换文件时, 常常遇到gbk编码与utf8编码, 需要转换可直接利用iconv进行
语法结构:
iconv -f 原编码 -t 新编码 filename -o newfile
常用参数
-f encoding :把字符从encoding编码开始转换。
-t encoding :把字符转换到encoding编码。
-l :列出已知的编码字符集合
-o file :指定输出文件
-c :忽略输出的非法字符
-s :禁止警告信息,但不是错误信息
--verbose :显示进度信息
栗子:
nihao_utf8=$(echo "你好")
nihao_gb2312=$(echo $nihao_utf8 | iconv -f utf8 -t gb2312 --verbose)
echo ${nihao_utf8}
echo ${nihao_gb2312}
正则小栗子:
url="https://www.cnblogs.com/yangyongzhi/archive/2012/11/05/2755421.html"
# 匹配url有效性
echo ${url} | grep -P -e "[a-zA-Z]+://[a-zA-Z0-9.?=@]+"
# 截取服务器类型
echo ${url} | grep -P -oe "[a-z]+(?=://)"
# 截取域名
echo ${url} | grep -P -oe "(?<=://)[^/]+(?=/)"
# 截取路径
name=`echo ${url} | grep -P -oe "(?<=://)[^/]+(?=/)"`
file=`echo ${url} | grep -P -oe "(?<=/)[^/]+$"`
echo ${url} | grep -P -oe "(?<=//${name}/).+(?=${file})"
# 截取文件名
echo ${url} | grep -P -oe "(?<=/)[^/]+$"
# 截取文件扩展名
echo ${file} | grep -P -oe "(?<=.)[^.]+$"
匹配长字符串:
一般文件都不仅仅只有一行, 这时使用正则就有点无力了
这里使用sed
源文件
Chapter 7 -- Exercises
7.1 please execute the program: mainwithoutreturn, and print the return value
of it with the command "echo $?", and then compare the return of the printf
function, they are the same.
7.2 it will depend on the exection mode, interactive or redirection to a file,
if interactive, the "output" action will accur after the n char with the line
buffer mode, else, it will be really "printed" after all of the strings have
been stayed in the buffer.
7.3 there is no another effective method in most OS. because argc and argv are
not global variables like environ.
cat shellTest2.sh | sed -n 7,9p
处理格式化文本
格式化文本主要指类似/etc/passwd
, tree
这种具有固定格式的文本
这里主要用到了cut
cut命令用于显示每行从开头算起 num1 到 num2 的文字
能够很方便的指定分隔符对字符串进行分割
cat /etc/passwd | cut -d":" -f1,5
指定分隔符为:
, 并显示第一行和第五行
多文件关联操作
其余就是join的使用
有点像数据库的联合查找, 当需要在多个文件间联合查找数据时, 可以使用join
有需要直接来看吧, 现在先放着
文件操作:
了解文件操作首先大致了解一下Linux文件存储的inode
参考博客:
https://blog.csdn.net/xuz0917/article/details/79473562
文件读取以块block为单位, 而inode存储文件的元信息, 其内容有点类似于文件控制块FCB
文件属性:
完成文件操作之前, 首先需要了解文件属性
struct stat {
dev_t st_dev; /* 设备 */
ino_t st_ino; /* 节点 */
mode_t st_mode; /* 模式 */
nlink_t st_nlink; /* 硬连接 */
uid_t st_uid; /* 用户ID */
gid_t st_gid; /* 组ID */
dev_t st_rdev; /* 设备类型 */
off_t st_off; /* 文件字节数 */
unsigned long st_blksize; /* 块大小 */
unsigned long st_blocks; /* 块数 */
time_t st_atime; /* 最后一次访问时间 */
time_t st_mtime; /* 最后一次修改时间 */
time_t st_ctime; /* 最后一次改变时间(指属性) */
};
ls -l 也能获取到部分文件信息:
这里以教程为例:
$ ls -l
total 12
drwxr-xr-x 2 root root 4096 2007-12-07 20:08 directory_file
prw-r--r-- 1 root root 0 2007-12-07 20:18 fifo_pipe
brw-r--r-- 1 root root 3, 1 2007-12-07 21:44 hda1_block_dev_file
crw-r--r-- 1 root root 1, 3 2007-12-07 21:43 null_char_dev_file
-rw-r--r-- 2 root root 506 2007-12-07 21:55 regular_file
-rw-r--r-- 2 root root 506 2007-12-07 21:55 regular_file_hard_link
lrwxrwxrwx 1 root root 12 2007-12-07 20:15 regular_file_soft_link -> regular_file
d
表示目录-
表示普通文件(或者硬链接)l
表示符号链接p
表示管道文件b
表示块设备c
表示字符设备s
表示socket
文件
不同属性的异同
普通文件 & 目录 这里就不进行阐述
-
有名管道文件
具有管道的特点: 为空时, 读取阻塞, 没有读取者时, 写入阻塞
主要用于进程通信
测试时可以使用两个terminal进行读写, 当没有echo > pipeFile时, cat pipefile将被阻塞
-
块设备 & 字符文件
字符设备与块设备的区别主要是, 字符设备发送&接收的数据是字符, 而块设备的数据传输是以数据缓冲区发送的, 如硬盘则是块设备, 以数据缓冲区为单位与系统交换信息, 而鼠标键盘这种低速设备则是字符设备, 传输字符数据
-
软链接 & 硬链接
这个在基础入门中有大致了解过
硬链接可以说就是原文件,软链接只是有那么一个
inode
,但没有实际的存储空间$ ls regular_file* ls regular_file* -l -rw-r--r-- 2 root root 204800 2007-12-07 22:30 regular_file -rw-r--r-- 2 root root 204800 2007-12-07 22:30 regular_file_hard_link lrwxrwxrwx 1 root root 12 2007-12-07 20:15 regular_file_soft_link -> regular_file $ rm regular_file # 删除原文件 $ cat regular_file_hard_link # 硬链接还在,而且里头的内容还有呢 fefe $ cat regular_file_soft_link cat: regular_file_soft_link: No such file or directory
普通文件再分类:
普通文件在windows系统下, 可通过后缀名进行在分类, 但在Linux系统中, 后缀名仅仅是为用户提供快速识别文件类型的途径, 操作系统是根据文件头识别各类文件的, 这样在解释文件时更不容易出错
使用file命令可以查看各类文件的属性, 通常用于进一步识别普通文件
file不同类型的文件
$ file ./
./: directory
$ file /etc/profile
/etc/profile: ASCII English text
$ file /lib/libc-2.5.so
/lib/libc-2.5.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped
$ file /bin/test
/bin/test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), stripped
$ file /dev/hda
/dev/hda: block special (3/0)
$ file /dev/console
/dev/console: character special (5/1)
$ cp /etc/profile .
$ tar zcf profile.tar.gz profile
$ file profile.tar.gz
profile.tar.gz: gzip compressed data, from Unix, last modified: Tue Jan 4 18:53:53 2000
$ mkfifo fifo_test
$ file fifo_test
fifo_test: fifo (named pipe)
文件属主
修改文件从属:
chown 用户名:组名 文件名
查看文件从属:
ls -l
其实现是通过文件结构体的用户&组ID, 查找/etc/passwd & /etc/group 中的用户名&组名来实现的
文件权限:
修改文件权限
入门必备, 这里不再阐述
给文件加锁
这里使用chattr命令
chattr常用与以超越用户权限的方式改变文件属性
语法结构:
chattr [ -RVf ] [ -v version ] [ mode ] files...
常用参数:
-A:即Atime,告诉系统不要修改对这个文件的最后访问时间。
-S:即Sync,一旦应用程序对这个文件执行了写操作,使系统立刻把修改的结果写到磁盘。
-a:即Append Only,系统只允许在这个文件之后追加数据,不允许任何进程覆盖或截断这个文件。如果目录具有这个属性,系统将只允许在这个目录下建立和修改文件,而不允许删除任何文件。
-b:不更新文件或目录的最后存取时间。
-c:将文件或目录压缩后存放。
-d:当dump程序执行时,该文件或目录不会被dump备份。
-D:检查压缩文件中的错误。
-i:即Immutable,系统不允许对这个文件进行任何的修改。如果目录具有这个属性,那么任何的进
程只能修改目录之下的文件,不允许建立和删除文件。
-s:彻底删除文件,不可恢复,因为是从磁盘上删除,然后用0填充文件所在区域。
-u:当一个应用程序请求删除这个文件,系统会保留其数据块以便以后能够恢复删除这个文件,用来防止意外删除文件或目录。
-t:文件系统支持尾部合并(tail-merging)。
-X:可以直接访问压缩文件的内容。
给文件加锁的方式就是打上immutable位, 即系统不允许对此文件进行任何修改
[hhtxzzj@localhost temp]$ sudo chattr +i shellTest2.sh
[sudo] password for hhtxzzj:
[hhtxzzj@localhost temp]$ ls -l
total 24
-rw-rw-r--. 1 hhtxzzj hhtxzzj 0 May 10 21:44 0
-rwxrwxrwx. 1 root root 65 Apr 27 16:05 makeFiles.sh
prw-rw-r--. 1 hhtxzzj hhtxzzj 0 May 13 10:29 pipeFile
-rwxrwxr-x. 1 hhtxzzj hhtxzzj 591 May 11 17:36 shellTest2.sh
-rwxrwxr-x. 1 hhtxzzj hhtxzzj 7098 May 12 22:08 shellTest.sh
-rw-rw-r--. 1 hhtxzzj hhtxzzj 546 May 9 22:48 temp2.tmp
-rw-rw-r--. 1 hhtxzzj hhtxzzj 1458 May 9 22:50 temp.tmp
使用chattr修改后的文件, 在ls -l中, 权限并没有变换
需要用lsattr
查看chattr修改后的文件属性
[hhtxzzj@localhost temp]$ lsattr shellTest2.sh
----i----------- shellTest2.sh
[hhtxzzj@localhost temp]$
可以看到, 文件当前只读
取消immutable后, lsattr的结果:
[hhtxzzj@localhost temp]$ sudo chattr -i shellTest2.sh
[sudo] password for hhtxzzj:
[hhtxzzj@localhost temp]$ lsattr shellTest2.sh
---------------- shellTest2.sh
[hhtxzzj@localhost temp]$
文件大小:
- 普通文件的大小就是文件内容的大小
- 目录作为一个特殊的文件, 存放的内容是以目录结构体组织的各类文件信息, 所以大小一般是固定的
- 设备文件的大小对应设备的主次设备号
- 有名管道(named pipe) 大小是0
- 硬链接实际上就是文件的拷贝, 大小就是源文件的大小
- 软链接的大小仅仅是一个inode, 所以大小就是源文件名的字节数
目录的结构体如下:
struct dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[NAME_MAX+1]; /* 文件名称 */
}
文件基本操作
这里就是一些文件的常用操作, 包括创建, 删除, 赋值, 修改, 编辑,压缩&解压
都是日常常用操作, 很熟悉, 这里直接略过
文件搜索
这里主要使用find进行文件查找
参考博客:
https://blog.csdn.net/lilygg/article/details/84076757
find 目录 参数 参数值
-name "name" 查找name文件
-user "user" 查找属于某用户的文件
-group "group" 查找属于某用户组的文件
-maxdepth 1 查看多深的文件,不能超过所限制的目录下的内容
-mindepth 2 查看不小于多深的文件,不低于所限制内容
# 这个要放到参数的最前头
-size 20K 按文件大小查找20K 的文件
-size -20K 查找不大于20K的文件
-size +20K 查找大于 20K的文件
# 这种+-在后头的参数中也有用到
-type 查找指定类型的文件
#主要的文件类型:
f #file 普通文件
d #dir 目录
b #block 块设备
s #socket 套接字
c #char 字符设备
l #link 链接
p #pipe 管道
-cmin 5 查看距现在5分钟时修改
-cmin -5 查看五分钟内修改的文件
-cmin +5 五分钟之前修改的文件
-ctime 5 五内的时间点修改过的文件
-ctime +5 五天前修改或的文件
-ctime -5 小于五天修改过的文件
-perm 按权限查找
-perm 555 查找权限为555的文件
-perm -444 查找所有人 所有组 其他人 有读权限的文件
-perm /444 查找所有人 或所有组 或其他人 至少有一个有读权限的文件
常用实例:
找到temp目录下7天之内以log结尾的文件, 并删除
find ./temp/ -type f -name "*log" -ctime -5 -print
而删除文件使用的是xargs
xargs用来给命令传递参数, 通常可以用在管道中
xargs详细命令:
https://www.linuxprobe.com/linux-xargs-usage.html
find ./temp/ -type f -name "*log" -ctime -5 -print | xargs -n 1 rm
也可以使用grep配合正则表达式执行
find . -type f | grep ".*log" | xargs rm -r
文件系统操作:
文件系统在Linux中的位置:
如图, 可以清楚的看到linux系统层次布局与文件系统所在的位置
由于文件系统无法独立与Linxu与硬件而存在, 所以有必要了解这俩
硬件管理 & 设备驱动
Linux 系统通过设备驱动管理硬件设备
如果添加了新的硬件设备,那么需要编写相应的硬件驱动来管理它。对于一些常见的硬件设备,系统已经自带了相应的驱动,编译内核时,选中它们,然后编译成内核的一部分或者以模块的方式编译。如果以模块的方式编译,那么可以在系统的 /lib/modules/$(uname -r)
目录下找到对应的模块文件
常用的设备驱动管理操作:
查找设备所需的驱动文件:
这里主要使用到了locate
命令
参考博客:
https://www.runoob.com/linux/linux-comm-locate.html
locate命令用于查找符合条件的文档
他会去保存文档和目录名称的数据库内进行查找, 速度很快, 但是需要更新文件索引数据库:
updatedb
通常只需要locate filename
即可查找到所需文件
其他需求直接去看参考博客
栗子:
locate vmxnet3.ko
以.ko
文件结尾的驱动, 在系统安装时, 默认被编译为了模块而并没有添加进内核中, 主要是为了降低内核的大小, 并可根据需要灵活的加载&卸载这些驱动
查看各个模块的状态:
文件系统中的/proc/modules
文件检查内核中已加载的各个模块的状态
cat /proc/modules
或者可以直接使用lsmod
命令进行
lsmod
查看已加载的设备驱动:
[hhtxzzj@localhost ~]$ lsmod | egrep "vm"
kvm_intel 188740 0
kvm 637289 1 kvm_intel
irqbypass 13503 1 kvm
vmw_balloon 18094 0
vmw_vmci 67168 0
vmwgfx 291993 1
drm_kms_helper 186531 2 vmwgfx,nvidia_drm
ttm 96673 1 vmwgfx
drm 456166 5 ttm,drm_kms_helper,vmwgfx,nvidia_drm
vmxnet3 58104 0
vmw_pvscsi 23130 0
卸载 & 挂载设备驱动:
rmmod 完整驱动名
这里的驱动名是lsmod
中列出的完整的驱动名
insmod 驱动路径
通常驱动路径使用locate
进行定位, 如:
insmod `locate usbhid.ko`
查看设备驱动对应的设备文件:
[hhtxzzj@localhost ~]$ ls -l /dev/sda*
brw-rw----. 1 root disk 8, 0 May 16 11:43 /dev/sda
brw-rw----. 1 root disk 8, 1 May 16 11:43 /dev/sda1
brw-rw----. 1 root disk 8, 2 May 16 11:43 /dev/sda2
brw-rw----. 1 root disk 8, 3 May 16 11:43 /dev/sda3
几个注意点:
-
第一列都是b, 表示这是一个块设备
-
第五列都是8, 是该硬件在内核中的对应设备编号
可以在内核的Documentation/devices.txt 和 /proc/devices 中找到设备的分配情况
-
第六列对应的设备的辅助编号, 用于区分同一设备的不同部分
可以看到, 系统只挂在了一块硬盘,但是设备文件有4个, 所以就需要辅助编号进行进一步的区分
访问设备文件:
根据上头的方法查找到对应的设备文件, 就可以直接访问设备了
这里使用到dd命令
参考博客:
https://www.cnblogs.com/ginvip/p/6370836.html
dd命令用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换
if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >
of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >
ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。
obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。
bs=bytes:同时设置读入/输出的块大小为bytes个字节。
cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。
skip=blocks:从输入文件开头跳过blocks个块后再开始复制。
seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
注意:通常只用当输出文件是磁盘或磁带时才有效,即备份到磁盘或磁带时才有效。
count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。
conv=conversion:用指定的参数转换文件:
ascii:转换ebcdic为ascii
ebcdic:转换ascii为ebcdic
ibm:转换ascii为alternate ebcdic
block:把每一行转换为长度为cbs,不足部分用空格填充
unblock:使每一行的长度都为cbs,不足部分用空格填充
lcase:把大写字符转换为小写字符
ucase:把小写字符转换为大写字符
swab:交换输入的每对字节
noerror:出错时不停止
notrunc:不截短输出文件
sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。
如用 dd
命令复制出硬盘的前 512 个字节
[hhtxzzj@localhost ~]$ sudo dd if=/dev/sda of=/home/hhtxzzj/shellTest/mbr.bin bs=512 count=1
[sudo] password for hhtxzzj:
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000149194 s, 3.4 MB/s
查看导出文件的相应信息:
[hhtxzzj@localhost shellTest]$ file mbr.bin
mbr.bin: x86 boot sector; partition 1: ID=0xee, starthead 0, startsector 1, 167772159 sectors, extended partition table (last)