linux操作系统基础(含C编译,make编译,shell脚本)

文章目录

  • 一、文件管理
  • 二、其他指令
  • 三、Ubuntu文件结构
  • 四、用户基本信息
    • 4.1 用户管理
  • 五、文件所属与权限
    • 5.1 文件权限
    • 5.2 修改文件所属用户
  • 六、软件安装
  • 七、磁盘管理(U盘)
  • 八、压缩与解压
  • 九、连接文件(硬连接、软连接)
  • 十、vim文本编辑器
  • 十一、C编程
  • 十二、make工具和makefile
  • 十三、Makefile基本语法
  • 十四、shell脚本

Linux终端快捷键

快捷键 含义
Tab 输入一部分命令按可以自动补齐
Ctrl+shift+ + 终端文字放大
Ctrl + - 终端文字缩小
Ctrl+L 清屏

一、文件管理

一些通用符号含义

./ 当前目录(不打点也是当前目录,如cd ./a和cd a)
../ 上一级目录(相对路径)
/ 根目录(绝对路径)
* 所有文件(用于删除、复制、移动等)
-l 详细信息(显示目录等)

文件操作常用命令

命令 含义 含义
clear 清屏
pwd 显示当前所在路径
ls 查看当前文件夹目录
ls -a 查看所有文件,包括隐藏文件
ls / 查看根目录内容
ls -l / 查看根目录详细信息
ls -l 查看目录详细信息
linux操作系统基础(含C编译,make编译,shell脚本)_第1张图片 ls -l查看的信息中,第一个字母含义:- 普通文件 d 文件夹,b 设备文件(块设备) c设备文件(字符设备) i连接文件 s 套接字文件 p 管道文件
cd 跳转目录
cd ~ 当前用户目录
cd a/b 跳转到当前目录里a目录下的b目录
cd / 根目录
cd - 上一次访问的目录
cd .. 上一级目录
touch 创建文件
touch 路径和名字 创建文件
touch test 当前目录创建test文件
touch test/a 在该目录下的test目录下创建a文件
touch test/a b 在当前文件的test文件夹下创建a文件,当前文件下创建b文件
mkdir 创建文件夹
mkdir aaa 在当前目录下创建aaa目录,相对路径
mkdir -v aaa
mkdir ./bbb 在当前目录下创建bbb目录,相对路径
mkdir /ccc 在根目录下创建ccc目录,绝对路径
mkdir -p /home/a/b 在home下创a,a下创b(需要加-p)
mkdir test/{a,b} 在当前母的的test文件夹创建a,b文件夹
mkdir -pv test/{a/{b,c},d} 在test下创a,d,在a下创b,c
cp 复制
cp /home/a/b/c /home/a/ 复制文件
cp -r /home/a/b/c /home/a/ 复制文件夹(文件夹需要加-r)
c -r /home/a/b/* /home/a/ 复制b下的所有文件到a
MV 移动
MV a/b/c a a中的b中的c移动到a中去
MV a/b/c a/d a中的b中的c移动到a中去并改名为d(前提是a中没有d文件夹,有d文件这则移动到a中的d文件夹内)
MV a/b a/c 将a中的b改名为c(前提是a中没有c)
rm 删除
rm -rf a/* 删除文件a内的所有文件夹和文件
rm -rf a/b* 删除文件a内的所有b开头的文件夹和文件
rm -rf a/*b 删除文件a内的所有b结尾的文件夹和文件
rm -rf a/a a/b 删除a里面的a和b
rm -rf bbb 强制删除当前目录下的bbb目录
rm -r bbb 询问是否删除bbb目录
rm -rf a.java 强制删除当前目录下的a.java文件
find 查找文件
find -name a 查看a文件夹
find -name a* 查看a开头的文件或文件夹
cat 查看文件内容(重点)
cat a.txt 查看a.txt文件
more 查看文件内容(翻页)
more a.txt 查看a文件(按回车键一行一行进行查看, 按空格键一页一页进行查看,q退出)
tail 查看文件后几行
tail -f a.java 查看文件后10行内容
tail -n 5 a.java 查看后5行内容
head 查看文件前几行
head a.java 查看文件前10行内容
head -n 5 a.java 查看前5行内容
grep 过滤,查找内容 -i忽略大小写,-n标出显示行的列数
grep c a.txt 查看文件a.txt内的包含c的内容
grep -nr “Ubuntu” / 在整个系统里面查找Ubuntu(包括文件内)
> 文件名 覆盖写入文件 ls > a.txt 将查询的结果写入a.txt中
>> 文件名 追加写入文件
ls > a.txt 将查询目录的结果写入a.txt中(>前面的内容一定是正常的指令,可有输出的)
geidt 文本编辑器
gedit a.txt 编辑a.txt
du 文件夹大小 (-h人类可读的方式显示)du -h --max-depth=1(只显示一级目录文件大小)
df 列出文件系统的整体磁盘使用量 (包含大小,已用,可用等数据)
| 管道(将管道左边命令的输出结果作为管道右边命令的输入) ls -l | more 将显示的内容分屏

二、其他指令

命令 含义 含义
uname 查看系统信息(加-a详细信息)
sudo 切换用户身份,提权
su 切换用户
ifconfig 显示网络配置信息
ifconfig 网卡名 down 关闭网卡
ifconfig 网卡名 hw enter 00:AA:BB:CC:DD:EE 修改MAC地址
ifconfig 网卡名 up 启动网卡
ifconfig 网卡名:ws arp 启动ARP
ifconfig 网卡名:ws -arp 关闭ARP
ifconfig 网卡名 mtu 1500 设置最大传输单元
reboot 重启
poweroff 关机
man 系统帮助
man printf 查看printf含义
sync 数据同步写入磁盘
df 磁盘空间检查
ps 当前系统进程查看命令 -aux显示所有行程,-au显示较详细咨询
top 进程实时运行状态
file 文件类型查看
echo 输出内容 echo $PATH输出路径

三、Ubuntu文件结构

linux操作系统基础(含C编译,make编译,shell脚本)_第2张图片

文件路径 含义
/bin 存放二进制可执行文件,这些指令在单用户模式下也能够使用,可以被root和一般的账号使用
/boot Ubuntu 内核和启动文件,比如 vmlinuz-xxx。gurb.引导装载程序
/dev 设备驱动文件(ls sd*可以查看U盘,从这进行装载)
/etc 存放一些系统配置文件,比如用户账号和密码文件,各种服务的起始地址
/home 系统默认的用户主文件夹,一般创建用户账户的时候,默认的用户主文件夹都会放到此目录下
/lib 存放库文件
/media 此目录下放置可插拔设备,比如 SD 卡,或者 U 盘就是挂载到这个目录中
/mnt 用户可使用的挂载点,如果要挂载一些额外的设备,那么就可以挂载到此处
/opt 可选的文件和程序存放目录,给第三方软件放置的目录
/root root 用户目录,也就是系统管理员目录。
/sbin 和/bin 类似,也是存放一些二进制可执行文件。sbin下面的一般是系统开机过程中所需要的命令。
/srv 服务相关目录。比如网络服务
/sys 记录内核信息,虚拟文件系统
/tmp 临时目录
/var 存放一些变化的文件,比如日志文件
/usr usr 不是 user 的缩写,而是 UNIXSoftware Resource 的缩写,存放于系统用户有关的文件,会占用很大的存储空间!“
/proc 虚拟文件系统,数据放置到内存中,存放系统运行信息

四、用户基本信息

指令 作用
cat 显示文件内容
cat /etc/passwd 查看用户基本信息
cat /etc/shadow 查看用户密码信息
cat /etc/group 查看组信息
cat user01 /etc/passwd 查看user01用户基本信息
ls /home/ 查看用户,创建了user01就有user01文件
id user01 用户user01存在则显示详细信息,不存在则提示没有
ls /var/spool/mail/user01 用户邮件
whoami 查看当前账户
grep hr /etc/group 查看组名包含hr的信息

用户基本信息文件:cat /etc/passwd,被冒号分成七列,同户名:x:uid:gid:描述:HOME:shell,每一行是一个用户信息
linux操作系统基础(含C编译,make编译,shell脚本)_第3张图片

列数 含义
x 密码占位符
uid 用户的身份证号(系统约定:RHEL7,uid:0特权用户,uid:1~499系统用户,uid:1000+普通用户)
gid 组号
描述 解释
HOME 家目录,登入系统时,所在的目录
shell 登入shell,命令解释器

用户密码信息(经过了加密)文件:cat /etc/shadow,被冒号分成九列,最后一列没意义

linux操作系统基础(含C编译,make编译,shell脚本)_第4张图片

列数 意义 含义
1 用户名
2 密码加密值 *表示被锁定,双汉号表示密码过期,$6$开头表示用SHA-512加密,$1$用MD5解密,$2$用Blowfish加密,$5$用SHA-256加密
3 最后一次修改时间 从某个时间至今天数
4 最小间隔 3表示过3天可改密码
5 最大时间间隔 密码有效期
6 警告时间 提示还有多久密码过期了
7 不活动时间 用户不登入系统天数,超过时间没登入则禁用
8 失效时间 账户的有效期,到了失效时间账户失效
9 保留 什么意思都没有

组信息文件:cat /etc/group,被冒号分成四列,root: x:0:组名:组密码:组ID:组成员

linux操作系统基础(含C编译,make编译,shell脚本)_第5张图片

4.1 用户管理

图形化创建要安装:sudo apt-get install gnome-system-tools(这里不介绍图像化操作)

用户在这个组,可以访问这个组内信息文件,可以共用空间,但不能访问其它组内信息文件(不在此组)。每个用户可以属于多个不同的组

#开头是超管用户(root用户),才可以创建用户等操作,$为普通用户没创建用户等操作能力
linux操作系统基础(含C编译,make编译,shell脚本)_第6张图片

用户

指令 作用
finger user01 用户查询
useradd user01 创建user01用户(-u指定组,-d /user01指定家目录为user01,)
adduser user01 创建user01用户(设置密码等信息)
passwd 修改当前账户密码(普通用户只能修改自己的,超管可以改其他账户)
passwd user01 修改user01用户密码(密文输入,输入看不到,无显示)
userdel -r user01 删除用户user01(不加-r删除后还保存文件)
usermod -s /sbin/nologin user01 修改用户属性,用户不能登入
usermod -s /bin/bash user01 修改用户属性,用户可以登入


一个用户有一个基本组(随用户而创建,一般组名用用户名),可以有多个额外加入的组为附加组(用户额外加入的组)

指令 作用
groups user01 查看user01用户在哪些组里面(显示格式:用户:组名
usermod -g user01 group01 修改user01的基本组
usermod -G group01 user01 修改user01的附加组(加-a添加不替换
usermod -a -G group01 user01 给用户user01添加group01组
groupadd hr 创造hr组(创建成功提示var/spool/mail/root中有邮件)(-u指定用户UID,-g指定用户的基本组,-G指定用户的附加组)
groupdel hr 删除组
gpasswd -d A GROUP 把用户A从GROUP组内移除
groupmod -g 1001 修改组ID
su - root 提权(进入root后exit退出root账户)(像root一样使用命令,但不是root)
sudo useradd user01 提权(在普通用户下加个sudo才可以拥有root的权限执行命令,否则不能)
# 举例
用户AA,基本组1508,附加组空
用户BB,基本组1509,附加组空
组CC,组号1510,和谁都没关系
usermod AA -g CC
执行上述指令后,用户AA,基本组1510,附加组空
usermod BB -G CC
执行上述指令后,用户BB,基本组1509,附加组1510
CC组有两个成员,一个AA,一个BB

案例
先创建个用户user01,user02
adduser user01,adduser user02
cat /etc/passwd
在这里插入图片描述
创建用户后会自动生成两个组,指令格式:groups 用户名,显示格式:用户名:组名
linux操作系统基础(含C编译,make编译,shell脚本)_第7张图片

再创建个用户组group01,group02,此时里面都没有用户
addgroup group01,addgroup group02
cat /etc/group
linux操作系统基础(含C编译,make编译,shell脚本)_第8张图片
将用户user01从user01组移动到group01组,显示格式:用户名:组名
linux操作系统基础(含C编译,make编译,shell脚本)_第9张图片
给用户user01添加个附加组,如果没有则添加,如果有则替换(加-a参数则是添加,不是替换,即usermod -a -G group01 user01)(刚开始没有附加组,直接添加,后来有附加组,没加-a参数,则替换,后来加了-a参数,再添加个附加组)
linux操作系统基础(含C编译,make编译,shell脚本)_第10张图片
将用户user01从group02中移除
linux操作系统基础(含C编译,make编译,shell脚本)_第11张图片
使用指令sudo deluser user01删除用户user01
使用指令sudo delgroup group01删除用户组group01

五、文件所属与权限

5.1 文件权限

文件状态:r为可读(r=4),w为可写(w=2),x为可执行(x=1)
可执行文件在命令行中运行./文件名就可以运行,比如,编写一个hello.c文件,运行gcc hello.c -o hello就会生成一个可执行文件,然后运行./hello即可运行)
linux操作系统基础(含C编译,make编译,shell脚本)_第12张图片

linux操作系统基础(含C编译,make编译,shell脚本)_第13张图片

使用ll查看文件,可以在左边看到文件的权限,左边方框内有10列,第一列表示文件类型,后面分为三个三组,第一组(2-4)用户权限,第二组(5-7)用户组内成员权限,第三组(8-10)其他用户权限
比如某文件显示如下 - rw- rw- r--:表示当前用户可读写无可执行,组内其他用户可读写无可执行,其他用户可读无可执行
linux操作系统基础(含C编译,make编译,shell脚本)_第14张图片

上面方框后面数字后的两个a,第一个表示a用户,第二个表示a用户组
文件权限修改
可以用二进制形式修改文件权限,可读为4(100),可写为2(010),可执行为1(001)
指令格式:chmod 参数 文件名
比如我们将b.txt权限改为可读可写可执行,则运行chmod 777 b.txt指令,如下图
linux操作系统基础(含C编译,make编译,shell脚本)_第15张图片

也可以用字母形式修改权限

字母 含义
r 可读权限
w 可写权限
x 可执行权限
a 所有用户
u 归属用户
g 归属组
o 其他用户
= 具备权限
+ 添加权限
- 移除权限

格式:chmod u/g/o/a+/-/=rwx
一定要注意格式顺序,先用户群体,再添加或删除,最后权限
比如我们将a.txt文件禁止组内其他用户编写,组内其他用户则是g(第二组),写为w,移除为-,则组合就是chomd g-w a.txt
linux操作系统基础(含C编译,make编译,shell脚本)_第16张图片

5.2 修改文件所属用户

比如我们将a用户下的a.txt改到root用户当中sudo chown root a.txt
linux操作系统基础(含C编译,make编译,shell脚本)_第17张图片

将a.txt的用户组有a改为root用户组sudo chown .root a.txt
linux操作系统基础(含C编译,make编译,shell脚本)_第18张图片
同时修改a.txt属与a用户和a用户组sudo chown a.a a.txt
linux操作系统基础(含C编译,make编译,shell脚本)_第19张图片
如果要将某文件内所有文件修改所属用户与用户组,则执行如下指令sudo chown -R 用户.用户组 文件夹名

六、软件安装

1、在应用商店下载

2、使用指令安装(apt工具):
sudo apt-get install 包名,如:sudo apt-get install git,再如sudo apt-get install mplayer(视频播放工具)

3、使用deb安装
首先在某网站官网下好安装包,即deb文件,相当于Windows下的exe,然后执行上面指令(在windows下,安装的是.exe文件,在Ubuntu中,安装的是.deb文件)
然后执行下面指令使用deb安装:sudo dpkg -i xxx.deb(卸载:sudo dpkg -r xxx
桌面上没有图标,我们在usr/share/applications目录下可以看到应用程序的桌面图标

4、自己下载源码编译
以tree为例,在网址下载:mama.indstate.edu/user/ice/tree
linux操作系统基础(含C编译,make编译,shell脚本)_第20张图片
下载之后,该文件里面有操作步骤文档(install文件)
linux操作系统基础(含C编译,make编译,shell脚本)_第21张图片

终端进入该文件夹
linux操作系统基础(含C编译,make编译,shell脚本)_第22张图片首先执行make,然后执行sudo make install下载完成
(执行不带sudo会提示permission没权限,需要嗲sudo)
(ubuntu里面要拥有make,gcc工具,没有则要下载)
安装好了之后,可以运行tree查看
linux操作系统基础(含C编译,make编译,shell脚本)_第23张图片

七、磁盘管理(U盘)

/dev/sd*文件,此类文件是磁盘设备文件,并不能直接访问磁盘,必须要将磁盘挂载到某一个目录下才可以访问

插上U盘后,可以在dev中查看U盘,在插U盘前后分别查看cd /dev,ls sd*,如下图可以看到有sdb和sdb1,sdb表示U盘,sdb1表示U盘的第一个分区
在这里插入图片描述
注:U盘要用FAT32格式的(在右击属性中可以查看),linux大部分系统都不支持NDFS格式的U盘
linux操作系统基础(含C编译,make编译,shell脚本)_第24张图片
U盘挂载与卸载

插上U盘后,如果没有默认挂载,可以查看到文件,但是cd进不去(如上cd sdb1),需要挂载之后才可以进去,这种情况下需要我们手动挂载

先在/media/a里面创建一个udisk用于挂载U盘
linux操作系统基础(含C编译,make编译,shell脚本)_第25张图片然后执行sudo mount -o iocharset=utf8 /dev/sdb1 /media/a/udisk进行U盘挂载,挂载成功后,media/a/udisk里面就有U盘的内容(-o iocharset=utf8防止中文乱码)
linux操作系统基础(含C编译,make编译,shell脚本)_第26张图片

执行sudo umount /media/a/udisk进行U盘卸载,后面是磁盘路劲,卸载后,此处就没有U盘内容
linux操作系统基础(含C编译,make编译,shell脚本)_第27张图片磁盘分区格式化
显示磁盘分区:sudo fdisk -l
sudo fdisk /dev/sdb,然后输入m获取帮助,然后按提示可以创建分区、删除分区(U盘处于挂载状态无法删除)等操作,操作完成之后输入w进行保存

使用sudo mkfs -t vfat /dev/sdb1进行格式化

八、压缩与解压

linux下常用的压缩格式有.tar,.tar.bz2,.tar.gz。因为linux下很多文件是.bz2,.gz的压缩文件,因此需要在windows下安装7.ZIP软件

指令 含义
gzip压缩工具 负责压缩和解压缩.gz格式的压缩包
gzip xxx 压缩文件(压缩后原文件没了
gzip -d xxx.gz 解压缩
gzip -r xxx 压缩文件夹(批量对文件夹里的文件压缩,并不是将这个文件夹打包压缩成一个
gzip -rd xxx.gz 解压文件夹
linux操作系统基础(含C编译,make编译,shell脚本)_第28张图片
bzip2 和gzip类似(效果一样),只负责压缩和解压bz2格式文件
bzip2 -z xxx 压缩文件(压缩后原文件没了
bzip2 -d xxx.gz 解压
linux操作系统基础(含C编译,make编译,shell脚本)_第29张图片
tar 提供打包服务,多个文件打包成一个(-c打包,-x提取,-j使用bzip2压缩格式,-z使用gzip格式,-v打印压缩过程)
tar -vcf a.tar a 将文件夹a打包成a.tar
tar -vxf a.tar 解压
tar -vxjf xxx.bz2 解压
tar -vcjf xxx.bz2 xxx 压缩
tar -vxzf xxx.tar.gz 解压
tar -vczf xxx.tzr.gz xxx 压缩
rar 安装:sudo apt-get install rar
rar x xxx.rar 解压缩(加x参数)
rar a xxx.rar x 压缩(加参数a)
zip zip格式(-r文件夹压缩,-v显示过程)
zip -rv xxx.zip zip 压缩
unzip xxx.zip 解压

九、连接文件(硬连接、软连接)

连接方式分为符号连接(软连接)和硬连接,符号连接类似于Windows下的快捷方式,硬连接通过文件系统的inode连接来产生新的文件名,而不是产生新文件。
inode:记录文件属性,一个文件一个inode。inode相当于文件ID,查找文件的时候要先找到inode,然后才能读取文件内容

ln命令
ln命令用户创建链接文件
命令格式:ln [选项] 源文件 目标文件
选项:-s创建符号连接(软连接)
-f强制创建链接文件,如果目标存在,那么先删除目标文件,然后再建立文件
硬连接
硬连接是多个文件都指向同一个 inode,硬连接知识点:
1、具有相同inode 的多个文件互为硬连接文件,创建硬连接相当于文件实体多了入口
2、对于硬连接文件,只有删除了源文件以及对应的所有硬连接文件,文件实体才会被删除
3、根据硬链接文件的特点,我们可以通过给文件创建硬连接的方式来防止文件误删除
4、不论修改源文件还是连接文件,另一个文件的数据都会被改变。
5、硬连接不能跨文件系统。
6、硬连接不能连接到目录

举例
原先只有一个hello可执行文件,利用ln hello hello1ln hello hello2建立两个硬连接(ll -i查看inode),运行./hello./hello1./hello2都可以运行
linux操作系统基础(含C编译,make编译,shell脚本)_第30张图片
此时我们将源文件hello删除,./hello1./hello2通用可以正常运行,删除原文件对其毫无影响,如果要删除,需要把连接和原文件都删除,即hellohello1hello2
linux操作系统基础(含C编译,make编译,shell脚本)_第31张图片
再如,我们对hello.c建立连接,查看内容是一样的
linux操作系统基础(含C编译,make编译,shell脚本)_第32张图片
我们对hello.c进行修改保存,可以发现hello1.c也跟着发生了变化
linux操作系统基础(含C编译,make编译,shell脚本)_第33张图片
linux操作系统基础(含C编译,make编译,shell脚本)_第34张图片

符号连接(软连接)
符号连接类似Windows 下的快捷方式,符号链接也叫做软连接,软连接要用的多。符号连接相当于创建了一个独立的文件,这个文件会让数据读取指向它连接的哪个文件的文件名。软连接的特点:

1、可以连接到目录。
2、可以跨文件系统。
3、删除源文件以后,软连接文件也就打不开了。
4、符号连接文件通过->来指示具体的连接文件。
5、符号连接要使用绝对路径,否则连接可能会出问题(拷贝cp(-d保留连接))

举例
我们用相对路径(容易出问题)和绝对路径分别举例,先建立连接,可以看到建立的链接文件比hello小很多
linux操作系统基础(含C编译,make编译,shell脚本)_第35张图片

现在三个文件都可以正常运行,可以看到暂时没什么问题
linux操作系统基础(含C编译,make编译,shell脚本)_第36张图片
当我们进行复制的时候,会出现问题,相对路径的就不能运行
在这里插入图片描述
当删除源文件的时候,可以发现建立的连接无法使用了
linux操作系统基础(含C编译,make编译,shell脚本)_第37张图片

十、vim文本编辑器

安装:sudo apt-get install vim

vim 文本编辑器
vim a.txt 编辑a.txt(进入一般模式),进入后按ia才可以编辑文件,进入编辑模式后要退出先按esc,然后输入:和字母,比如:wq表示保存退出,:q!不保存退出。,:set nu设置行号,:set list显示控制字符,:set nonu取消设置行号,:w只保存不退出,:1,5 s/333/666/g一到五行的333换成,:w /tmp/a.txt另存为tmp下的a.txt
vim只进入,没有进入编辑,一些字母含义,yy复制(前面可以先按数字),p粘贴,d删除,u后退一步(撤销),v可视化(等于鼠标选择,选择后按Y可以复制),0行首,$行尾,G最后一行,gg第一行,6G第六行,/adm查找adm(enter查找,n跳转下一个,N上一个)
临时文件:vim未正常关闭产生的文件(如vim编辑a.txt未正常关闭产生.a.txt.swap),再次编辑是报错 解决方案:查看影藏文件:ls -a,删除临文件

十一、C编程

vim默认TAB键为8空格,需要将其改为4空格,在/etc/vim/vimrc文件添加set ts=4(需要加sudo),添加set nu显示行号
linux操作系统基础(含C编译,make编译,shell脚本)_第38张图片
使用vim helo.c编写一个hello.c文件,内容如下
linux操作系统基础(含C编译,make编译,shell脚本)_第39张图片

使用指令gcc hello.c -o hello(或者分两步,gcc -c hello.c生成hello.o文件,执行gcc hello.o -o hello链接成hello可执行文件)编译C程序,编译结束之后会生成一个hello可执行文件,运行./hello即可运行(-o指定输出文件名,-v显示编译过程)
linux操作系统基础(含C编译,make编译,shell脚本)_第40张图片
如果程序有误,使用gcc编译会报错,比如将hello.c修改缺少一个冒号,如下
linux操作系统基础(含C编译,make编译,shell脚本)_第41张图片
此时使用gcc编译会报错
linux操作系统基础(含C编译,make编译,shell脚本)_第42张图片

十二、make工具和makefile

当源码文件比较多的时候就不适合通过直接输入gcc命令来编译,这时候就需要一个自动化的编译工具。

make工具可以完成自动编译工作,如果修改了几个源文件,则侧重编译这几个修改的源文件;如果某个头文件修改了,则从新编译所有包含该头文件的源文件。make一般用于将源代码文件编译为可执行的二进制文件。make 工具编译的时候需要 Makefile 文件提供编译文件。

Makefile是make 工具所使用的文件,Makefile 指明了编译规则
makefile规则

目标...: 依赖文件集合...
	命令1
	命令2
	...

比如下面这条规则:

main: main.o  input.o  calcu.o
	gcc -o main main.o input.o calcu.o

这条规则的目标是main,main.o、input.o和calcu.o是生成main的依赖文件,如果要更新目标main,就必须要先更新它的所有依赖文件,如果依赖文件任何一个有更新,那么目标也必须更新,更新就是执行一遍规则中的命令列表(命令列表中的每条命令必须以TAB键开始,不能使用空格

make命令会为makefile中的每个以TAB开始的命令创建一个shell进程去执行

完整的指令:如下要生成main,需要依赖main.o,input.o,calcu.o,如果都存在,则执行命令gcc -o main main.o input.o calcu.o生成main,如果某个更新的依赖没有,则从下面找哪个指令生成的目标是这个依赖,然后执行生成依赖

main:	main.o 	input.o 	calcu.o
	gcc	-o	main	main.o	input.o	calcu.o
main.o:	main.c
	gcc	-c	main.c
imput.o:	input.c
	gcc	-c	input.c
calcu.o:	calcu.c
	gcc	-c	calcu.c

clean:
	rm	*.o
	rm	main

举例
首先创建文件main.c,内容如下:

#include
#include "input.h"
#include "calcu.h"

int main(int argc, char *argv[])
{
	int a, b, num;
	input_int(&a, &b);
	num = calcu(a, b);
	printf("%d + %d = %d\r\n", a, b, num);
	return 0;
}

再创建文件input.c,内容如下:

#include
#include "input.h"

void input_int(int *a, int *b)
{
	printf("input tow num:");
	scanf("%d %d", a, b);
	printf("\r\n");
}

再创建文件calcu.c,内容如下:

#include

int calcu(int a, int b)
{
	return (a + b);
}

创建头文件input.h内容如下:

#ifndef __INPUT_H
#define __INPUT_H

void input_int(int *a, int *b);
#endif

创建头文件calcu.h文件如下:

#ifndef __CALCU_H
#define __CALCU_H

void calcu(int a, int b);
#endif

总共5个文件
linux操作系统基础(含C编译,make编译,shell脚本)_第43张图片

如果我们用gcc编译,则需要将所有的.c文件都输入,即指令为:gcc main.c calcu.c input.c -o main生成可执行文件,然后./main运行程序
linux操作系统基础(含C编译,make编译,shell脚本)_第44张图片这里使用gcc编译需要输入所有的.c文件,且会全部重新编译,耗时费力不方便。使用make可以方便很多,make只会对修改过的文件进行编译,不会全局编译,这里我们编写Makefile文件
linux操作系统基础(含C编译,make编译,shell脚本)_第45张图片

编写完之后,然后执行make指令编译,会生成对应的.o文件和可执行文件,运行./main即可执行
linux操作系统基础(含C编译,make编译,shell脚本)_第46张图片

如果要清除那些.o文件和可执行文件,运行make clean即可(上面makefile中编写了clean)
linux操作系统基础(含C编译,make编译,shell脚本)_第47张图片
这里如果修改一个文件,从新执行make,就会对修改过的文件进行编译,不会执行未修改的文件

十三、Makefile基本语法

Makefile可以定义变量,如下面语句可以定义一个变量等于main.o input.o calcu.o,简化书写过程

main: main.o  input.o  calcu.o
	gcc -o main main.o input.o calcu.o

简化成如下

#Makefile变量使用
bojects	=	main.o  input.o  calcu.o
main:	$(objects)
	gcc	-o	main	$(objects)

=赋值,在原变量发送变化后,被该变量赋的值也会变化(如下面的curname)
在Makefile里面编写如下内容
linux操作系统基础(含C编译,make编译,shell脚本)_第48张图片
运行make print得到如下结果(echo前面没加@输出了编译过程)
在这里插入图片描述
echo前面加个@,就不输出过程,只输出结果,没有命令这行
linux操作系统基础(含C编译,make编译,shell脚本)_第49张图片

在这里插入图片描述
:=赋值,原变量发生变化,被赋值的变量不发送改变,curname等于原始的aa,不随name的改变而改变,而=赋值会跟着发送变化,代码如下
linux操作系统基础(含C编译,make编译,shell脚本)_第50张图片
在这里插入图片描述
?=表示如果前面没有被赋值,则赋值该值,如果前面赋值了,则使用之前的值,比如name1先赋值为aa,然后?=bb,由于原先赋值了,这里就打印原先的值,name2没有赋值,则值为cc,代码如下:
linux操作系统基础(含C编译,make编译,shell脚本)_第51张图片
在这里插入图片描述

+=追加内容,原先name内容为aa,后来使用+=符号追加bb,然后打印出来为aabb,代码如下:
linux操作系统基础(含C编译,make编译,shell脚本)_第52张图片
在这里插入图片描述

main:	main.o 	input.o 	calcu.o
	gcc	-o	main	main.o	input.o	calcu.o
main.o:	main.c
	gcc	-c	main.c
imput.o:	input.c
	gcc	-c	input.c
calcu.o:	calcu.c
	gcc	-c	calcu.c

clean:
	rm	*.o
	rm	main

上面这个是一般规则,使用起来需要全部写上去,这里可以使用模式规则进行简化,在规则的目标定义中要包含%,%表示对文件名的匹配,%表示任意长度的字符串,比如%.c表示所有以.c结尾的文件,a.%.c表示所有以a.开头,以.c结尾的文件,目标中%所代表的值决定了依赖中的%值,上面的指令可以简化为如下(指令简化的gcc命令中运用到了自动化变量):

linux操作系统基础(含C编译,make编译,shell脚本)_第53张图片

自动化变量 描述
$@ 规则中的目标集合,在模式规则中,如果有多个目标的话,“$@”表示匹配模式中定义的目标集合。
$% 当目标是函数库的时候表示规则中的目标成员名,如果目标不是函数库文件,那么其值为空。
$< 依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么“$<”就是符合模式的一系列的文件集合。
$? 所有比目标新的依赖目标集合,以空格分开。
$^ 所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个重复的文件“s^”会去除重复的依赖文件,值保留一份。
$+ 和“s^”类似,但是当依赖文件存在重复的话不会去除重复的依赖文件。
$* 这个变量表示目标模式中"%"及其之前的部分,如果目标是 test/a.test.c,目标模式为 a.%.c,那么“$*”就是 test/a.test。

伪目标
当没有定义伪目标的时候,Makefile里面有如下内容
在这里插入图片描述
在外面运行make print就会有输出结果
在这里插入图片描述
如果在该文件夹里面存在print文件,则运行make print就不能正常使用
linux操作系统基础(含C编译,make编译,shell脚本)_第54张图片

这是需要将Makefile里面对print使用伪目标(.PHONY:print),这时候就可以正常使用make print指令
在这里插入图片描述
linux操作系统基础(含C编译,make编译,shell脚本)_第55张图片
条件关键字:ifeq,ifneq,ifdef,ifndef
ifeq和ifneq用来判断是否相等,ifeq用来判断是否相等,ifneq判断是否不相等(下面指令用来表示参数1与参数2是否会相同

ifeq	(<参数1>,	<参数2>)
ifeq	'<参数1>',	'<参数2>'
ifeq	"<参数1>",	"<参数2>"

ifdef和ifndef用法如下

ifndef<变量名>

如果变量名的值非空,则表达式为真,否则为假

Makefile函数使用
不支持我们自定义函数,使用方法如下

$(函数名	参数集合)

或者

${函数名	参数集合}

参数集合是函数的多个参数,参数之间用逗号隔开,函数名与参数之间用空格隔开,函数调用以$开头,常用函数如下

函数 含义
subst 字符串替换 $(subst ,,)将text中的from内容替换为to,函数返回替换后的字符串
patsubst 模式字符串替换 $(patsubst ,,)查找text中的单词是否符合模式pattern,如果匹配就用replacement来替换,如$(patsubst %.c,%.o,a.c b.c c.c)将o,a.c b.c c.c中符合%.c的字符串替换为%.o
dir 获取目录 $(dir )获取/src/a.c目录部分,也就是/src
notdir 去除文件中的目录部分 $(notdir )获取/src/a.c非目录部分,也就是a.c
foreach 完成循环 $(foreach ,,)把list中的单词逐一取出放到var中,然后再执行text所包含的表达式,每次text都会返回一个字符串,循环过程中,text中所包含的每个字符串会以空格隔开

十四、shell脚本

shell脚本类似于Windows下的批处理文件,shell脚本是将连续执行的命令写成一个文件(linux下的.sh文件),shell脚本提供数组、循环、条件判断功能。shell脚本第一行一定是内容#!/bin/bash表示使用bash

下面建立一个简单的脚本,新建文件my.sh,内容如下:
在这里插入图片描述
此时该文件不是可执行文件,需要修改权限,然后运行可以输出hello world
linux操作系统基础(含C编译,make编译,shell脚本)_第56张图片
交互式shell脚本:使用read输入
比如,让用户输入字符串,然后将其打印
在这里插入图片描述
linux操作系统基础(含C编译,make编译,shell脚本)_第57张图片
可以加-p用于提示符,比如如下输入两个值
在这里插入图片描述
在这里插入图片描述

shell脚本数值计算:仅支持整形,数值计算使用$((表达式))
注:total中间的等号前后不能加空格
linux操作系统基础(含C编译,make编译,shell脚本)_第58张图片
linux操作系统基础(含C编译,make编译,shell脚本)_第59张图片

test命令用于查看文件是否存在、权限等信息,可以进行数值、字符、文件三方面的测试,这里会用到&&||,比如cmd1 && cmd2表示当cmd1执行完且正确,接着执行cmd2,否则不执行;cmd1 || cmd2表示当cmd1执行完且正确,则不执行cmd2,否则执行

举例:查看某个文件是否存在,如果不存在则输出不存在,如果存在,则输出存在
linux操作系统基础(含C编译,make编译,shell脚本)_第60张图片linux操作系统基础(含C编译,make编译,shell脚本)_第61张图片
再如,用test判断两个字符串是否相等
linux操作系统基础(含C编译,make编译,shell脚本)_第62张图片
linux操作系统基础(含C编译,make编译,shell脚本)_第63张图片

中括号判断符,里面只能是==或者!=(中括号里面一定要用引号,中括号前后一定要有空格

linux操作系统基础(含C编译,make编译,shell脚本)_第64张图片

linux操作系统基础(含C编译,make编译,shell脚本)_第65张图片
默认变量:$0-$n表示运行脚本参数,包括shell脚本本身,shell脚本命令本身为$0$#表示最后一个参数的标号,$@表示$1,$2,$3...

举例:编写my.sh文件,然后带参数运行./my.sh a b
linux操作系统基础(含C编译,make编译,shell脚本)_第66张图片
linux操作系统基础(含C编译,make编译,shell脚本)_第67张图片
shell脚本条件判断
shell脚本提供了if then条件判断

if 条件; then
	判断成立执行语句
fi

还有if then else语句

if 条件判断;then
	判断成立执行
else
	判断不成立执行
fi

还有if then elif then

if 条件判断;then
	判断成立执行
elif 条件判断;then
	判断成立执行
else
	判断不成立执行
fi

举例:输入两个数字,然后输入符号,根据符号不同进行不同运算
linux操作系统基础(含C编译,make编译,shell脚本)_第68张图片
linux操作系统基础(含C编译,make编译,shell脚本)_第69张图片

还有case语句

case $变量 in
"第一个变量")
	程序段
	;;  //表示该程序块接收
"第二个变量")
	程序段
	;;
...
"第n个变量")
	程序段
	;;
esac

举例:(上面的都不符合进入*)
linux操作系统基础(含C编译,make编译,shell脚本)_第70张图片
linux操作系统基础(含C编译,make编译,shell脚本)_第71张图片

shell脚本函数

function fname(){
	代码
}

举例:prin是调用函数
linux操作系统基础(含C编译,make编译,shell脚本)_第72张图片
在这里插入图片描述
举例:函数传参
linux操作系统基础(含C编译,make编译,shell脚本)_第73张图片
在这里插入图片描述
shell循环
while do done

while 条件
do
	代码
done

还有until do done 表示条件不成立的时候循环,条件成立就不循环

until 条件
do
	代码
done

举例,如果不输出close,程序就不会结束
linux操作系统基础(含C编译,make编译,shell脚本)_第74张图片linux操作系统基础(含C编译,make编译,shell脚本)_第75张图片

for循环可以知道循环次数

for var in con1 con2 con3...
do
	代码
done

或者

for((初始值;限制值;执行步长))
do
	代码
done

举例:
linux操作系统基础(含C编译,make编译,shell脚本)_第76张图片
linux操作系统基础(含C编译,make编译,shell脚本)_第77张图片
举例:输入数字,计算1+2+3加到该数的和

在这里插入图片描述
在这里插入图片描述

你可能感兴趣的:(Linux,linux,运维,服务器)