linux课件完整汇总

Linux 专栏收录该内容
2 篇文章 0 订阅

第一章 Linux历史与系统安装

Linux是一个开源的操作系统内核,发布与GPL协议,全称是GNU/Linux

Linux参考了Unix的设计思想

重启网络服务: sudo /etc/init.d/networking restart

查看IP地址:ip addr 或ifconfig

重启: reroot

 

第二章 目录结构与磁盘管理

文件系统是操作系统用于在外部存储设备(主要是硬盘)上组织文件的机制。Ubuntu 16.04默认Ext4

Linux没有“盘符”的概念,通过一个整体的目录树来组织文件

目录            说明

/                    系统根目录

/usr               用户的程序,配置等信息

/bin              存放常用命令的目录,和/sbin目录存放系统最核心的命令

/home           主目录,所有用户主目录都会在此目录下,以用户名命名

/sbin              超级用户root才能使用的命令所在目录

/lib                系统动态链接共享库

/boot             root用户的主目录

/etc                系统配置文件以及一些程序的配置文件都在此目录

/dev              外接设备会映射为此目录下的一个文件

/media           把系统自动识别的u盘,光盘等挂载到此目录下

/proc             一个虚拟目录,是系统内存的映射,可以获取系统以及进程的信息

/sys               一个虚拟目录,把硬件设备映射成文件,可以通过文件控制硬件

/lost+found   一般为空,系统异常关机时会有一些信息存入此目录

/var              存放一些不断变化增长的东西(如日志文件)

/usr/bin         用户程序目录

/usr/sbin        需要超级用户权限运行的程序所在的目录

/tmp              存放临时文件的目录

 

命令              说明

ls                   显示目录/文件

cd                  切换工作目录

df                  查看磁盘使用情况

fdisk              磁盘格式化

mkfs              创建文件系统

mount           挂载设备

umount         卸载设备

 

ls -a              显示目录下的所有内容,包括以 . 开头的隐藏文件

ls -l               以详细方式显示目录内容信息

ls -R             递归显示目录内容

ls -S              按文件大小排序,大的在前

使用man is可查看ls命令帮助手册

 

cd (changedirectory)

cd ..              回到上一层目录,在根目录/下使用还是根目录

cd ~              在任何目录下使用

cd -               进入上一次使用的目录

/dev /sd[a-z]  表示硬盘设备(老式的IDE硬盘用hd表示)

sda1, sad2…   表示分区

/dev下cdrom、dvd等表示光盘存储设备

 

df -h             以易于读取的方式显示空间使用情况

df -T              显示文件系统的类型

 

fdisk -l           列出已安装的所有磁盘的分区

fdisk-l<disk> 列出指定磁盘的分区

运行sudo fdisk/dev/sda,根据提示,输入m可获取帮助信息

d                   进入删除分区的子步骤

l                    显示所有Ubuntu支持的文件系统格式

n                   进入创建分区的子步骤,其中p用来创建主分区,e用来创建扩展分区

p                   打印修改后的分区表。这个分区表还没有写入硬盘,只是保存在内存中

w                   把分区表写入硬盘,q放弃修改

 

mkfs (makefilesystem)

mkfs -f<文件系统类型><设备分区>

mkswap /dev/sda5       创建交换文件系统

 

mount -r /dev/sdb2/media/c                                 只读模式挂载

mount -t ext4/dev/sdb2 /media/c                          指定ext4文件系统,一般不用,mount会自动识别文件系统类型

mount -t iso9660 -oloop ./Ubuntu.iso /media/iso  挂载ISO文件

umount /media/c                                                   卸载挂载点

 

注意

U盘对应/dev 目录下的sdx文件。这个时候,可以使用fdisk进行分区等操作,但是若想读取U盘中的文件,必须进行挂载:       sudo mount /dev/sdb1/media/u

使用完毕,要用umount/media/u 进行卸载

而要使用fdisk对U盘/硬盘等其他已挂载的存储设备进行分区操作,则必须要先卸载才可以。

 

配置双网卡

安装ssh服务: sudo apt-get install openssh-server

终端命令:sudo printf“\nauto enp0s8 \n iface enp0s8 inet dhcp \n” >>  /etc/network/interfaces (可能失败)

或者进入文件页面修改:修改网卡配置:sudonano /etc/network/interferes

在下面面直接输入:autoenp0s8

iface enp0s8 inet dhcp

ctrl+x退出,提示保存Y,然后按enter确认

重启网络服务:sudo/etc/init.d/networking  restart

 

第三章 命令终端基础

终端:也称终端设备,是计算机最外围的设备,主要获取用户信息的输入以及处理结果的输出等

终端是一个设备。而shell是一个程序、主要就是获取用户输入的命令并运行,把结果返回给用户。终端最重要的事情是输入和输出,程序运行的结果要通过shell显示在终端上以此和用户产生交互

Linux命令分类

内部命令:属于Shell解释器的一部分,是shell程序自带的命令

外部命令:独立与Shell解释器之外的程序文件,是在系统的某个路径下的可执行程序,由shell依照事先设定好的路径查找,找到后才能执行

type<command>查找<command>是内部命令还是外部命令。hash表会缓存外部命令所在位置。刚开机时,hash表为空,每次运行命令,hash表会缓存此命令的路径,提高命令查找效率

which/whereis<command>查找<command>命令所在的路径

Linux命令格式

 Linux命令的通用格式为:命令 [选项] [参数]

 选项的含义:

       选项:用于调节命令的具体功能

              以”-”引导短格式选项(单个字符),例如”-l”

              以”—“引导长格式选项(多个字符),例如”--color”

       多个短格式选项可以写在一起,例如”-al”,但是这和程序设计方式有关,如果程序不支持这种格式则不能这样使用

 参数:命令操作的对象,如文件、目录名等

 选项和参数都是人为划分的,对程序来说,比如C语言的main(int argc, char *argv[])函数,后面的选项和参数都会传递到argv,都是作为main函数的参数传递的。

获得命令帮助

使用help查看Bash内部命令的帮助信息

命令的”—help”选项适用于大多数外部命令

使用man命令阅读手册页:man [COMMAND] ,↑↓滚动,PgUp PgDn翻页,q退出,按/后查找内容

命令搜索路径

bash会根据PATH变量的设置自动寻找输入的命令。如果有同名的命令,按照路径顺序找到后返回执行,不再继续寻找。有同名的命令可以输入路径运行

profile记录了bash会在哪些目录查找命令

默认的路径搜索顺序(用;隔开)

  ~/bin  ;~/.local/bin /usr/local/sbin ;

/usr/local/bin ; /usr/sbin ; /usr/bin

/sbin ; /bin ; /usr/games ; /usr/local/games

添加其他路径

  如果在用户主目录下存在ins目录,并希望添加到PATH环境变量中,可以在用户主目录下找到。profile文件,使用文本编辑器打开

PATH=后面的双引号中的字符串末尾添加 :/home/brave/in,保存文件

其中/home/brave是用户主目录,个人使用应换成自己的用户名

或者是直接使用$HOME/ins,$HOME会自动替换为当前用户的主目录

然后运行source  .profile

这样就可以直接在shell中输入ins目录下存在的程序名称被shell执行了

可以使用env命令显示系统中已存在的环境变量

shell使用小技巧

Tab键可以自动补全命令名称以及参数

命令历史:bash中可以使用↑↓逐条翻看,允许编辑并重复执行,history命令显示所有缓存在 .bash_history中的命令,history -c清空历史命令

快捷键

Ctrl+a 跳转行首,Ctrl+e 跳转行尾

Ctrl+l 清屏

Ctrl+c 终止程序执行

Ctrl+d 退出shell,回到登录界面

Ctrl+w 按单词删除,空格隔开的作为一个独立的词。

终端常用命令

命令              说明

ls                   列出文件、目录的信息

cd                  切换当前工作目录

mkdir            创建目录

rmdir             删除空目录

touch             创建空文件

rm                 删除给定的文件和目录。如果不为空,需要使用rm -rf

cp                  将一个或多个源文件或者目录复制到指定的目的文件或目录

mv                对文件或目录重新命名,或者将文件从一个目录转移到另一个目录中

cat                 连接文件并打印到标准输出设备上。cat经常用来显示文件的内容

more less       以全屏幕的方式按页显示文本文件的内容,less功能比more更强大

find               在指定目录下查找文件

常用命令使用示例

ls /usr            显示/usr的目录内容

ls -R /usr       递归显示目录内容

ls -l /usr        显示目录/文件详细信息

mkdir abc      在当前目录下创建abc目录

rmdir abc/      删除当前目录下的abc目录,abc必须是空目录

rm tmp/a.sh   删除tmp目录下的a.sh文件

rm -rf tmp/    删除tmp目录,目录可以不为空,会删除目录下所有的内容

cp tmp/a,sh sh/            复制tmp/a.sh文件到sh目录,tmp和sh都是当前目录的子目录

cp tmp/a.sh /tmp         复制tmp/a.sh到/tmp,/tmp是绝对路径

cp tmp/a.sh sh/b.sh     复制tmp/a.sh到sh/目录并为b.sh

cp mariadb/ -R /usr/local           递归复制mariadb目录到/usr/local

mv tmp/a.sh sh/                         移动文件

mv tmp/a.sh sh/b.sh                  移动文件并重命名

mv tmp/a.sh tmp/c.sh                重命名文件

touch tmp/test.sh                       在tmp目录创建test.sh空文件

cat /etc/passwd                          显示/etc/passwd文件的内容

find /usr -name gcc                   查找名称为gcc的文件,大小写敏感

find /usr -name gcc*                  查找名称gcc开头的文件,大小写敏感

find /usr/ -iname gcc*                查找名称开头gcc的文件,大小写不敏感

env                                            显示环境变量

 

第四章 IO重定向与管道

标准输入输出

       每个进程都至少有3个信道:标准输入-STDIN、标准输出-STDOUT、标准错误-STDERR

              标准输入:文件描述符为0,默认指向终端(在虚拟终端中即为键盘)

              标准输出:文件描述符为1,默认指向终端(在虚拟终端中即为屏幕)

              标准错误:文件描述符为2,默认指向终端(在虚拟终端中即为屏幕)

       在Linux中一切皆文件,所以标准输入、标准输出、标准错误都有对应的文件,而这种对应关系是通过文件描述来实

现的,我们在重定向的时候还会用到它们

    对于一个进程来说,它从描述符0指向的文件读取输入信息,把执行结果送到描述符1指向的文件,把出错信息送到

描述符2指向的文件,而不关心这些文件具体是什么

    关于文件描述符:一个进程有一个结构保存一组打开的文件,每个打开的文件用一个数字标识,此数字一般被称为文

件描述符,而在Linux/Unix上设备也被映射为文件,数字0,1,2都会分别关联到键盘,屏幕,屏幕

IO重定向

       在shell中输入命令运行程序,程序的正常输出信息(标准输出)和一些出错信息(标准错误)会通过shell显示在屏

幕上。有时候我们并不需要把这些输出信息(包括标准输出和标准错误)显示在屏幕上,或需要把这些输出信息保存在

一个文件中,这时就需要进行输出重定向。如果一个命令要获取的输入来自文件,或者是在shell脚本编程中,需要从

文件获取输入,则需要进行输入重定向

    重定向示例:echo‘abc’会输出abc到屏幕。echo ‘abc’ >tmp/buff会把abc输出到tmp/buff这个文件。如果没有此

文件则会创建这个文件并写入。但是如果文件存在并且不为空,则重定向会导致之前的数据丢失,只保存重定向的数据。

echo ‘abc’ >> /tmp/buff会把abc追加到文件末尾,之前的数据不会丢失

    谁控制重定向:在shell中使用>,<,>>等重定向符号时,执行重定向操作的是shell,而不是程序。shell把重定向符号解释成指令,将标准输入、输出、错误输出指向其他文件,而不是所关联的设备。手动编写的程序也是可以进行重定向的,但是在shell中输入命令,shell会创建子进程去执行命令,此时进行重定向操作的是shell

    重定向符号:shell将>,<,>>解释成指令,用来把一条命令的输入或输出重定向到一个文件。重定向STDERR的话,则用2>

类型                  操作符                                用途

重定向标准输入     <               将命令中接收输入的途径由默认的键盘更改为指定的文件

重定向标准输出         >               以替换的方式将命令的执行结果输出到指定的文件,而不是直接显示在屏幕上

                                  >>             将命令执行的结果追加输出到指定文件

重定向标准错误         2>              清空指定文件的内容,并将标准错误信息保存到该文件中

                                 2>>             将标准错误信息追加输出到指定的文件中

重定向标准输出   &>或>&         将标准输出、标准错误的内容全部保存到指定的文件中,而不是直接显示在屏幕上

和标准错误

重定向示例:

    wc -l newfile 与 wc -l < newfile

           wc是一个计算行数的程序,第一个是对文件进行操作;第二个是对文件内容进行操作,把文件的内容作为输入

    find / -iname gcc* >find_tmp

           标准输出重定向到find_tmp文件,但是错误信息会显示在屏幕上,如果需要把错误信息也重定向到文件,可以

运行:find / -iname gcc* &> find_tmp

       1>等同于>,0<等同于<,即前导的0和1可以省略,如果不省略,数字和重定向符号之间没有空格,前导2不可以

省略

管道

       把一条命令的STDOUT连接到另一条命令的STDIN上,可以用 | 这个符号,在shell中表示管道。shell在解释命令

遇到 | 时会创建管道,并创建两个进程,把标准输入输出重定向到管道,前一个进程向管道写数据,后一个进程从管道

读数据。在管道中只有标准输出才传递给下一个命令,标准错误输出直接输出到终端

管道和重定向示例

    查找名称含有curl的文件进行计数,并把错误信息重定向到/dev/null

           find / -iname *gcc*2> /dev/null | wc -l

    查找名称含有ssh的进程

           ps -ef | grep ssh

    分页查看内容

           ls -l -R /usr/share| less

    排序文件

           ls | sort -r

    分页查看帮助文档/文件

           help test | less

           cat /etc/passwd | less

 

第五章 用户和组管理

Linux是一个多用户多任务的系统,它基于用户身份对资源访问进行控制

Linux中的用户分三类:超级用户:root

普通用户:系统安装时创建的用户及后期使用中由用户创建的用户

系统用户:系统及服务运行时必须存在的用户,但与真是的普通用户有所不同,默认情况下是不能

登陆下系统的,他们的存在主要是满足系统进程对文件属主的需求。一般用户系统服务

用户信息文件passwd

       用户信息保存在/etc/passed文件中,每一行对应一个用户的账号记录,可以使用 cat/etc/passwd 命令查看其中保存

的信息

    文件中每行的格式为:

           登录名:口令:用户标识号:组标识号:注释性描述:主目录:登陆后启动的SHELL

用户密码信息文件shadow

       /etc/shadow文件保存的是用户密码加密后的数据,每一行对应一个用户的密码记录,每个用户对应/etc/passwd 中

的用户,只有root权限才可以读取

    shadow文件字段用:分隔,依次为:

           登录名

加密的密码:!表示无密码,*表示系统用户,不能登录

最近一次修改密码的时间:距离1970年1月1日的天数

密码的最短有效天数:默认为0,表示无限制

密码的最长有效天数:默认为99999

提前多少天警告用户口令将过期:默认为7

       此文件不要手动更改,应该由程序去操作

组的概念

       按照不同的角度,Linux中的组可以有不同的分法。

       第一种分为超级用户组(rootgroup)、系统组(system group)和用户组(usergroup)。超级用户组是超级用户所属的

组,系统组是系统用户所属的组,用户组是普通用户所属的组

       第二种分为基本组和附加组。用户所属组中的第一个组成为基本组,基本组在 /etc/passwd 文件中指定;用户所在的

其他组为附加组,附加组在 /etc/group 文件中指定。不可以把用户从基本组中删除,但是可以从附加组中删除。一个

用户可以属于多个附加组,但是一个用户只能有一个基本组

第三种分为私有组和公共组。建立账户时,若没有指定账户所属的组,系统会建立一个和用户名相同的组,这个组就是私有组,这个组只容纳了一个用户。而公共组可以容纳多个用户

    属于多个组的用户所拥有的权限是它所在的组的权限之和

组信息文件group

       /etc/group文件保存系统中所有组的信息

       第一个字段是组名;第二个字段是组密码,同样显示密码占位符x,真正的密码已经加密存放在 /etc/gshadow文件

中;第三个字段是组标识号;第四个字段是以此组为附加组的用户列表

       查看用户所属的组:groups查看当前用户所属的组;groups [user]查看[user]所属的组;id [user]同时查看用户信息和

组信息

Root用户

       root用户具有最高权限,它的UID是0。在Ubuntu上以root用户登陆时提示符会变成#,其他用户提示符是$

       经常有人把root和Windows下的administrator做对比,表面上看二者都是系统最高级别管理员,但是它们其实是有

区别的。Windows下有SYSTEM用户,SYSTEM才是最高权限用户,但仅限系统自己使用,administrator的权限也 没

有SYSTEM的权限大。而Linux下的root用户可以做一切事情,甚至可以直接毁掉整个系统

    可以修改 /etc/passwd文件中的uid为0,使普通用户获得和root一样的权限

 

su

    Su:(switch user切换用户),可让一个普通用户切换为超级用户或其他用户,并可临时拥有所切换用户的权限,切换

时需输入要切换用户的密码;也可以让超级用户切换为普通用户,临时以低权限身份处理事务,切换时无需输入密码

    用法:su[选项][用户名]。后边不带 username使用时,su默认会切换到超级用户

    带-, -l, --login选项可以切换到其他用户、示例:su – oklinux

    Su root和su一样,切换后以root身份执行命令,但当前工作目录不变

sudo

       sudo允许程序临时以root身份运行。sudo默认是以root身份运行命令,但是使用-u [username]可以以其他用户身

份运行命令

    sudo是受限制的su,它通过一个配置文件,授权某些用户可以临时具有root用户才有的权限(5分钟)

    sudo读取 /etc/sudoers 文件的信息以判断当前用户是否有权限运行sudo。运行sudo输入的是当前用户的密码,

这样使用授权的方式杜绝了root密码的泄露,同时可以根据需要进行用户授权

    如果是root用户,不需要使用sudo

    示例(获取软件更新):sudo apt update

设置密码

       passwd用于设置用户密码:sudo passwd [username]

       在Ubuntu上,root用户默认是没有密码的,安装过程也不会设置。如果想要设置root用户的密码,可在安装完成

后,运行命令: sudo passwd root

       sudo–i表示以root身份登陆,主目录也切换为root的主目录。为了频繁地执行某些只有超级用户才能执行的命令而不用每次输入密码,可以使用该命令。提示输入密码时该密码为当前账户的密码。没有时间限制。执行该命令后提示符变为#而不是$。想退回普通账户时可以执行exit和logout

添加用户:adduser

       此命令默认会创建主目录,创建的是普通用户,但是可通过选项创建不能登陆的系统用户

       用法:adduser [--home DIR] [--shell SHELL] [==no-create-home]

              [--uidID] [--ingroup GROUP | --gid ID]

              [-disabled-password][--disabled-login] user

       示例:

              sudoadduser --shell  /bin/bash  oklinux  //创建hellolinux用户,默认登录shell是bash

sudo adduser --shell /bin/bash  ubuntu1  --gid 1001 //指定要添加的组

sudo adduser  --shell  /usr/sbin/nologin  --no-create-home  --system --disabledpassword  --disabled-

login  mysql    //创建系统用户mysq

删除用户:deluser

       sudodeluser [username] 此操作不会删除主目录

       sudodeluser –remove-home [username] 删除用户并删除主目录

       sudodeluser –remove-all-files [username] 删除用户以及系统中一切属于此用户的文件

创建组以及删除组

       Sudoaddgroup [--gid ID] [group]

              --gidID 手动指定组ID

       另一种创建组的方法:sudo adduser –group [--gid ID] [group]

       删除组:sudo delgroup [group]

其他命令示例:

       给oklinux用户添加brave组:sudousermod –G brave –a oklinux

       从brave组中移除oklinux用户:sudogpasswd –d oklinux brave

本节课任务

创建用户组:genius

创建用户:brain,要求用户属于genius用户组

切换到brain用户,并创建目录task

运行命令:id 并且把结果保存到task/

 

第六章 安装/卸载软件

Debian/Ubuntu系列使用的软件包格式

.deb格式是Debian/Ubuntu使用的格式

.deb文件是一个压缩包格式,可以解压软件包查看内容

解压后的软件包就是已经编译好的程序,配置文件,手册等

软件包中的目录结构对于系统的目录结构,存放于系统的目录对应的位置,并记录安装信息,这就是安装过程

解压deb包:把toilet软件解压到toilet目录:sudo dpkg -Xtoilet_0.3-1.1_amd64.deb toilet

dpkg

dpkg是Dubian/Ubuntu上管理本地软件包的命令。dpkg不会联网查询软件包信息

dpkg示例:

       sudodpkg –install vscode.deb

       sudodpkg –remove vscode

       sudodpkg -l //列出所有软件包的信息

spkg不解决包依赖问题。所有依赖的包都要提供才可以安装

软件安装与卸载相关的命令

apt                从软件源安装软件,卸载软件,获取更新,系统更新升级等

dpkg             安装本地deb软件包,卸载软件等

aot-cache      从软件源搜索软件

apt-get          安装/卸载软件,系统更新等

apt随Ubuntu16.04一起发布。目的在于提供完整的更加结构化的功能,基本上整合了apt-get , apt-cache , apt-config三个命令的功能。

apt安装软件示例

运行sudo apt-get install sl

完成后,输入sl查看结果

apt是一个新工具,基本的使用和apt-get相同,但不是完全兼容,apt是为了替代apt-get而发布的

apt与软件源

/etc/apt/source.list记录了软件源的地址,#开头表示注释

apt安装软件时,会先从可用软件包信息中查找,找到通常会询问是否安装,确认后会从软件源下载deb包并安装,apt会解决包依赖问题

可以使用vim直接编辑source.list文件更改软件源地址

apt安装,卸载软件

安装软件:sudo apt install [PACKAGE NAME] ,多个软件用空格分开,以安装软件会检查更新。

e.g: sudo apt install atop saibar

卸载软件:sudo apt remove [PACKAGE NAME] ,使用形式参考安装软件

sudo apt autoremove 会删除所有自动安装且已经不再使用的包

系统更新与升级

获取系统以及软件的更新信息:sudo apt update

更新软件包:sudo apt upgrade或者是sudo apt full-upgrade,使用full-upgrade会进行整体的操作,如果一个软件的依赖关系发生变化,会先卸载软件再安装

本节课任务

安装tree软件

查找含有tree的文件,并把结果保存到文件a,不要输出错误信息

获取系统更新信息

系统与软件升级

 

第七章 文件编辑

编辑工具:nano和vim。都是终端模式的编辑器

nano使用

nano [FILE NAME]就可以打开一个文件,如果不存在则会创建

nano是打开文件就可以直接编辑的,并且默认启动窗口底部会显示常用快捷键选项

编辑快捷键:ctrl+o写入,ctrl+x退出

配置文件:/etc/nanorc

vim与vi

vi提供三种模式:

       命令模式:输入命令对文档等进行操作

       输入模式:编辑文本,左下角显—INSERT—

       底行模式:输入:会在文档最后一行显示;并等待输入命令,执行完成后会自动返回命令模式

vim是vi的增强版,支持配色主题,有大量插件,可以打造强大的IDE环境。并且提供win支持,同时vim支持GUI模式

vim安装与启动

终端输入vi或是vim.tiny可以启动编辑器。如果没有安装vim则运行sudo apt install vim,再启动vim

使用vim [filename]可以创建文件,此时进入vim是命令模式,esc用于模式切换,命令模式输入a,I,o进行插入操作,会切换到输入模式,按esc回到命令模式

vim基本操作

启动vim后,进入命令模式

       h:光标左移

       j:光标移到下一行

       k:光标移到上一行

       l:光标右移

       X:删除前面的字符

       X:删除后面的字符

       输入i:当前位置插入;a:后一个位置插入;o:下一行插入

vim使用的是命令的组合

输入模式按esc返回指令模式

       :w  写入文件

       :q  退出文件

       :wq  写入并退出

       :q!  不保存退出

       d       删除/剪切                  dd    删除当前行

d$    删除到行尾的内容    2dd   会重复两次运行dd命令

yy    复制当前行          p    粘贴

V     选中整行,此时移动光标可以成块选中

v     从光标标记位置开始选中

u     撤销更改

Ctrl+R 恢复更改             R大写

0      到行首 ; $ 到行尾

输入:0会定位到第一行,:$定位到最后一行。

输入:help获取帮助文档,输入:help [帮助文档名]获取具体信息

vim搜索和替换

:/php                    搜索所有匹配php的行,输入n跳转到下一个匹配,b定位到上一个匹配

:s/php/c                替换当前行第一个php出现的位置为c

:s/php/c/g             替换当前行所有匹配位置

:%s/php/c/             替换所有行第一个php位置为c

:%s/php/c/g           替换所有行所有位置

:5.%s/php/c            替换第5行到最后一行

:1,5s/php/c            替换的是第1到第5行

vim配置文件

默认安装的vim配置文件在/etc/vimrc。

在用户主目录下,创建.vimrc文件也是vim默认读取的配置文件。

vim在启动时会先读取/etc/vimrc,然后是.vimrc ,重复的配置,.vimrc会覆 盖/etc/vimrc的配置

在vim中运行本地命令

:!ls

:!后面跟名称,这种方式可以在不退出vim的情况下执行其他操作

本节课任务

获取/var/dpkg/available 的内容保存到tmp/pkg

使用vim打开文件,替换所有的Package为Program

保存并退出

思考:使用vim编写Python程序,路径为:py/a.py,但是程序写完之后,发 现py目录不存在,无法保存,此时如何在不退出vim的情况下保存文件?

 

第八章 文件管理

在Linux上,一切皆是文件。外接设备也会被映射为文件,在/dev目录下

目录是一种特殊文件,记录的是其他文件的信息

文件名区分大小写

Linux文件系统简明解释

磁盘被分割成块进行存储,称为扇区。一般一个扇区512字节。文件系统在此基础上把数据存储分为Boot block, Super block, i-node table, Data blocks几个区域。实际存储数据的是Data blocks

Super block存储文件系统类型、i-node table大小等信息。

i-node记录文件在Datablocks的存储位置

Boot block对于可启动分区有用。

如果系统安装在此分区,则此区域存储启动信息
                                                  

在系统层面来说,实际是通过文件路径名称找到文件的i-node然后对文件数据进行操作。目录文件记录了其他文件的文件名与i-node,对于用户使用来说,这些都是透明的,用户并不需要关心这些。

相关命令

ls                                 列出文件/目录信息

stat                              显示文件详细信息

rmdir                          删除空目录

cp , rm , mv               依次为复制,删除,移动

ln                                创建硬链接或符号链接

chmod                        更改文件权限以及更改文件所有者

chown                        更改文件所有者

cp tmp/a tmp/b          复制tmp/a文件,到tmp目录,命名为b

cp c/fst.c tmp/              复制c/fst.c文件到tmp目录,名称不变

cp –R c/  tmp/         递归复制目录c到tmp

rmdir tmp                    删除tmp目录,目录必须为空

rm c/test.c                   删除c/test.c文件

rm -rf tmp                  强制删除tmp目录,目录不为空也可以删除

mv c/fst bin/             移动c/fst文件到bin目录

mv c/fst1  bin/fst     移动c/fst1文件到bin目录,命名为fst

stat tmp/run             显示文件详细信息

列出文件权限等信息

shell中输入ls  -l

第一项表示文件对应的inode号;第二项d表示目录,l表示链接文件,-是普通文件,r,w,x分别表示可读,可写,可执行。连续三个分别表示文件所属用户具有的权限,文件所属组具有的权限,其他用户具有的权限。-表示没有权限。第三项是文件的硬链接数。第四,五项是文件所属用户和文件所属组。第六项是文件大小,字节为单位。接下来是创建时间,文件名。

文件权限与标志位

r:可读

w:可写,可以更改文件/目录的内容,可以删除文件/目录。

x:可执行,程序要具有可执行权限。目录必须要有可执行权限才可以进入。

八进制采用三个位表示,r,w,x占有的位分别为: r :100; w:010; x:001
                                                    

文件默认权限

系统创建文件时是有一个默认权限的,通过使用权限掩码进行默认权限的设置。

使用umask命令可以查看/设置权限掩码: umask 显示权限掩码 umask 022设置权限掩码

系统不允许在创建一个文件时就赋予它执行权限,必须在创建后用chmod命令增加这一权限;但是目录则允许设置执行权限。

默认权限计算规则:用777按位减去掩码中的相应位,并且文件还要减去可执行位。

更改文件权限

使用chmod命令改变文件与目录的权限。

使用示例:

chmod 755bin/pse rwxr-xr-x

chmod +x  bin/pse                          添加可执行权限,所属用户与用户组具备执行权限

chmod -w  bin/pse                          去掉写权限,用户,用户组,其他用户都会去掉写权限

chmodu=rwx,g=rx,o=r  bin/pse      相当于chmod 754  bin/pse

更改文件所属用户与所属组

使用chown更改文件所属用户和用户组。

示例:

chownoklinux:oklinux hd1                 更改hd1文件所属用户为oklinux,所属用户组 为oklinux

chown:brave  hd1                          更改hd1文件所属用户组

chown oklinux:hd1                          更改文件所属用户

chownoklinux:oklinux tmp/ -R        递归更改所有文件/目录的用户以及用户组

硬链接(hard link)

ln [TARGET] [LINK NAME]  默认创建硬连接。

示例:ln $PWD/hd1 hd2 会在当前目录创建文件的硬链接hd2。

在执行连接之前,存放连接的目录中不能有与链接名同名的文件。如果创建硬连接,则TARGET文件必须存在,并且不能是目录。

硬链接并没有建立新文件。相当于文件有一个别名,多个文件名使用一个 inode,增加了文件的硬链接计数。rm删除文件会减少硬链接计数,计数为0才会从文件系统中删除。

inode 号仅在各文件系统下是唯一的,当 Linux 挂载多个文件系统后将出现 inode号重复的现象。所以创建硬链接不能跨文件系统也不能跨分区。

软链接/符号链接(soft link/symbolic link)

符号链接类似于Windows上的快捷方式。

ln –s [TARGET] [LINK NAME]。用ln -s命令建立符号连接时, TARGET最好用绝对路径。

示例:ln -s/bin/date $HOME/bin/t。在主目录下的bin目录创建符 号链接t指向/bin/date。

创建符号链接就会创建一个文件,此文件记录的是另一个文件的路径。删除源文件或目录,只删除了数据,不会删除软链接。一旦以同样文件名创建了源文件,连接将继续指向该文件。

符号链接的大小是其指向文件名称的字节数。

符号链接可以跨分区跨文件系统,在实际使用中,符号链接很普遍。

本节课任务

在当前用户主目录创建目录:stu

使用vim创建文件 stu/a.sh,并写入以下内容:

#!/bin/bash

echo ‘Hello,this is my first shell program’

echo ‘Yoursystem info:’

uname -a

给stu/a.sh文件加入可执行权限,并运行stu/a.sh

用户主目录创建bin

对stu/a.sh创建符号链接:bin/fi

运行 source .profile

运行fi

 

第九章 进程管理

进程基本介绍

运行中的程序就是进程。系统会给每一个进程分配一个数字进行标记,此数 字就是进程ID(PID)。

父进程:如果进程B由进程A来创建,则进程A就是进程B的父进程,进程B就是进程A的子进程。

PPID:父进程的进程ID。

在shell中输入命令运行,则shell就是父进程,运行的程序就是shell的子进程。 (守护进程除外,守护进程的父进程是

init[进程ID为1])。

UID,EUID,GID,EGID

UID( user id ):每一个进程都有一个所属用户ID,就是运行程序的用户的 ID。每一个进程都有一个父进程,通常情况下子进程的UID继承自父进程。 但是系统通过系统调用传递参数更改进程的UID以标识进程的创建者。

EUID(effective userid):有效用户ID,表示进程对于文件和资源的访问权 限。大多数情况下EUID和UID是相同的。对于设置了相关标志位的程序,运 行时会改变EUID,系统根据EUID赋予进程相应的权限。

GID(group id):进程的组ID,程序所属组的ID,参考UID解释。

EGID(effectivegroup id):有效组ID,参考EUID解释。

进程管理相关的命令

ps                        查看当前进程

kill                       向进程发送信号,通常是终止进程

bg shell                内建命令,后台任务继续执行,就像在命令后面加入&

fg shell                 内建命令,后台任务转至前台

jobs shell              内建命令,显示后台运行的任务

pgrep                  搜索进程

top/htop              动态监控进程情况,系统资源使用情况

nice/renice           调整进程优先级

查看进程

使用示例:

ps -e  //查看所有进程

ps -u  root //查看所有root用户的进程

ps -aux //查看详细信息,如有效用户,pid,CPU占用,内存占用等

ps -ejH //显示进程树

ps  -l [PID]  显示进程详细信息

运行 man ps 查看ps手册。

分页查看进程信息: ps -aux | less

按列显示:ps -o user,pid,ppid,tty,comm,args -e

根据名称关键字搜索进程

Linux提供了pgrep命令查询进程信息。

使用方式: pgrep [options] KEYWORD

pgrep –a sh 搜索名称含有sh的进程,并列出详细信息。

pgrep –l sh 仅仅列出名称和PID。

另一种方式:ps -e | grep KEYWORD

终止进程:kill

kill:向指定的进程发送信号。kill –l 查看所有的信号。

示例:

kill 1234 //向PID为1234的进程发送终止信号。

默认的信号是SIGTERM,此信号通常会终止程序的运行,但程序可能仍然 继续运行。这个时候可以向进程传递SIGKILL信

号,会强制进程结束。

kill -9 1234 //向PID为1234的进程发送kill信号。

SIGINT,使用ctrl+c终止程序运行时发送的就是SIGINT信号,SIGINT、SIGTERM可以被程序捕获并进行自定义处理,而

SIGKILL不能被捕获。

后台任务

一个任务如果运行时间太长,或者是需要长期运行的情况,此时想要获取终 端控制权。可以把任务转至后台。

在命令后面加入&便可以直接使任务直接在后台运行。

而在运行中输入Ctrl+Z会把当前任务转至后台暂停。此时使用jobs可以显示 后台的任务,每个任务都有一个编号。使用

bg [ 后台任务编号 ]可以使任务在 后台继续执行。

fg [ 后台任务编号 ]把后台的任务转至前台执行。

进程优先级

运行nice会显示当前shell的优先级。一般情况下,子进程会继承父进程的优先级。系统内核在进程运行时也会动态调整。

nice ps 会在当前优先级加上一个数值(默认是10)运行ps。nice调整数字 的范围是-20~ 19。数字越小优先级越高。

renice [VALUE]  [PID]  调整进程优先级,[VALUE]  是一个整数,如果是负数 则只有root权限才可以执行。

通过ps查询发现有一个PRI项,PRI是系统内核动态调整的优先级参数,实际 的运行优先级是PRI+NI。

动态监控进程以及资源占用

Ubuntu自带top命令动态查看进程。htop是top的升级版。

htop需要下载安装,安装命令:sudoapt-get install htop。

saidar可以动态监控资源占用,但不显示进程的信息。pstree树形结构 显示进程信息。

sudo apt install saidar pstree

pstree使用: pstree–p  //显示进程ID

本节课任务

使用vim创建文件tm.sh,并写入以下内容: while date ; do sleep 1 clear done

给tm.sh添加可执行权限

运行tm.sh           ./tm.sh

把tm.sh转入后台

 

第十章 网络命令与配置

ip                         显示IP地址,MAC地址等信息

ping                     检测网络连接是否连通。

netstat netstat      命令显示网络连接、路由表、接口统计等信息。

ss                         用于获取套接字统计信息。它可以显示类似于 netstat 的信息。netstat 有些过时了,ss更具优势。

nethogs NetHogs 是一个轻便的网络监控工具。

iftop iftop             命令监听指定接口(如 eth0)上的网络通信情况。

Ip命令

ip help                         查看帮助信息。

ip [COMMAND] help    查看具体指令的帮助信息。示例: ip  address help

ip address                   显示网卡以及IP地址,MAC地址等信息。

为eth0网卡分配IP地址: ip address add 192.168.180.102/24  dev eth0

列出路由表:ip route  show

在ip命令之前都是使用ifconfig命令,这是一个已经被废弃的命令。

ss, netstat

ss可以替代netstat,netstat有些过时了,效率上不如ss,尤其是服务器维持 大量网络连接的时候,netstat非常慢,而ss很快,效率很高。

ss使用示例:

ss -t -a          显示所有TCP套接字

ss -a –p        显示所有套接字以及使用套接字的进程

ss -altp         显示所有正在监听的TCP连接

iftop, nethogs

iftop和nethogs需要安装:sudo apt install iftop nethogs

iftop监听网络通信情况。运行时需要root权限:sudo iftop

nethogs监控进程的带宽占用情况。

运行nethogs也需要root权限:sudo nethogs

网络配置文件

Ubuntu16.04以及之前版本在配置文件/etc/network/interfaces记录了网络接 口(网卡)的配置,网络服务根据此配置初始化网络服务。

Ubuntu16.04以及之前版本使用ifup和ifdown启用和停用网卡。ifdown命令慎用,远程服务器托管在机房,可能停用就导致本地客户端连接中断,此时就无法远程连接操作服务器了。

Ubuntu18.04版本改动比较大,使用netplan替换了ifup,ifdown。18.04版本的配置在/etc/netplan/***;星号表示配置文件,Server版本和Desktop版本配置 文件名称不同。

在测试机器上,UbutnuServer18.04的配置文件为: /etc/netplan/50-cloud-init.yaml

Ubuntu16.04上重启网络服务:sudo /etc/init.d/networking restart 或者是 sudo servicenetworking restart

Ubuntu18.04启用网络配置:sudo netplan apply

Curl

curl是一个命令行模式网络客户端工具,支持SFTP,HTTP,HTTPS, SMTP,POP3等协议。

使用示例: curl ’10.7.1.3:3456’

// 提交表单 curl -d‘user=hello&passwd=123456’ ’10.7.1.3:3456’

本节课任务

vim编辑网络配置文件,给网卡分配一个静态IP。

重启网络服务。

使用putty用分配的静态IP地址连接虚拟机系统。

 

期中复习

相对路径和绝对路径

基础命令:ls cd pwd mkdir cp mv rm rmdir ln lesscat

超级用户权限:sudo su

用户和组:adduser  addgroup delgroup  deluser

文件权限:chmod chown

进程:ps kill  bg  fg jobs

匹配查找:grep find

文本编辑:vim nano

重定向和管道:< >  2>  &> >> |

 

第十一章 shell脚本基础-变量

Shell在系统的角色

shell是用户和系统交互的桥梁:

shell是Linux的一个程序,实现版本有多种。shell的主要工作就是运行命令。

sh是shell的简写,shell的实现版本有:sh,bash,csh,tcsh,zsh。

多数Linux默认的shell是bash。Linux启动登录以后,会运行一个shell等待用户输入命令。

用户通过shell和系统交互。

Shell环境变量

当前shell运行时保存的信息,包括终端类型,当前目录,主目录,语言编码,默认命令搜索路径等信息。运行env命令可以查看当前环境变量。

环境变量是一个名称和值的对应列表。一种是shell启动时解析配置文件生成,还有一种临时的环境变量是在shell中使用export生成。

PATH变量记录了要查找命令的路径顺序;HOME记录当前用户主目录; PWD是当前工作目录,每次切换目录都会变化。使用$取值:echo $PWD,而echo PWD仅仅是输出PWD字符串。

Shell运行命令的基本过程

Shell运行命令的文字描述

输入一条命令并确认后,实际shell获取的是一行字符串,shell要对字符串进行解析,并确定命令名称,参数等信息。shell支持从文件读取文本逐 条解释执行。

然后,shell要根据配置文件的搜索路径,从每个路径寻找命令,没有找到则提示错误信息,找到就调用Linux提供的系统调用运行命令。

比如:输入 ls -l,shell要解析成‘ls’ ,‘-l’,’ls’就是命令名称,并在PATH设置的路径中寻找,找到/bin/ls这个命令,fork一个子进程调用 execv等系统调用传递参数运行命令。并等待结束。

注意:真正运行命令的不是shell,而是内核,shell去调用内核提供的接口,shell是调用fork创建子进程去运行命令。

Shell中的通配符

shell支持通配符,使用*表示匹配任意长度的字符,?匹配任意一个字符。

shell在遇到通配符会进行扩展,比如输入ls  ./a*,会匹配a开头的所有文件并显示,如果存在ab.txt,ac.txt,则会扩成ls  ./ab.txt ./ac.txt。

注意:扩展通配符的是shell,不是命令自身,如果是命令本身实现的,那就每个命令都要实现。

通配符在使用时会带来很多便利,但是有些特殊情况也要注意。

Shell脚本

shell可以从一个文件读取命令并逐条执行。文件一般被称为脚本。

大多数Linux发行版的默认shell都是bash。

文件第一行使用#!/bin/bash表明这是一个bash脚本,注意有些脚本程序使用 #!/bin/sh表示。

在Ubuntu/Debian上,sh是一个符号链接指向dash,dash是一个专为执行脚本而设计的shell程序,执行速度快,语法遵循POSIX标准,但是功能比bash 少很多。

一个简单的脚本:开头声明这是一个bash脚本,然后是主要操作代码,最后 以exit 0退出。

脚本的可执行权限

执行脚本可以使用 bash [SCRIPT NAME],此时bash读取脚本文件并执行, #!/bin/bash是被解释为注释。

另一种方式就是给脚本添加可执行权限:chmod +x [SCRIPT NAME]

给脚本添加执行权限,脚本开头的#!/bin/bash声明这是一个脚本文件,要用 /bin/bash执行。

变量

shell运行a=123就定义了a变量。shell中的变量就是为某些需要保存的数据用一个名称标记,方便以后使用。变量的名称以字母或是下划线符号开头,后可跟任意长度的字母、数字、下划线。

=左右不能有空格,否则会按照运行命令的方式去执行。

a=`ls` 会把ls运行的结果赋值给a。注意ls不是被单引号包含,而是反 引号。

获取变量的值要用$,echo $a可以输出变量的值。

shell中的变量就是键值对(key-value)的列表,都是以文本的形式存储的。a=1+2不会进行计算把3赋值给a,而是a的值就是‘1+2’这段文本。变量的值可以用双引号/单引号括起来,包含空格的变量就必须要这么做。

变量查看与清除

用set命令可以查看所有的变量。

可以使用 set | grep linux 进行搜索

unset VAR命令可以清除变量VAR,相当于没有定义过。使用空格分隔多个变量。

只读变量

变量设置后,是可以修改值的:a=12; a=13,此时a的值就是13

readonly把变量设置为只读:readonlya

但是设置之后,只读变量就无法更改和清除。除非重置shell环境。

 

算术运算

shell支持算术运算,并且shell会对$((····))里的算数表达式进行运算。 a=12;b=14

x=$(($a+$b))

echo  $x

如果b=12a,此时会报错,但是如果以字母开头的文本,比如b=a12, 则x=$(($a+$b))则直接就计算为a的数值,b转成数字为0。

逻辑运算

逻辑运算:&&,||, !。分别是AND,OR,NOT。

对逻辑运算来说,任何非0值都是真。

示例:echo $((1&&0))  ;  echo $(( 2 || 0))

非数字格式逻辑运算:

b=abc

echo  $(( 1 && $b ))  //输出是0

/*************/

b=12a

echo $(( 1&& $b)) //提示错误

放进环境变量

环境变量是全局存在的,在任何shell脚本中都可以直接使用。

使用env查看环境变量。

export a:把变量放到环境变量,环境变量是一个名称与值的简单列表。

使用示例,shell中执行:

$ env | greplinux

$ linux=1

$ export linux

$ env | greplinux

变量的引用

${#var}   返回变量值(字符串)的长度

${var:start_index}   返回从start_index开始一直到字符串结尾的字符串

${var:start_index:length}  返回从start_index开始的length个字符

${var:-newstring}  如果var未定义或为空值,则返回newstring;否则返回var 的值

${var:=newstring}  如果var未定义或为空值,则返回newstring,并把 newstring赋给var;否则返回var的值

${var:+newstring}  如果var不为空,则返回newstring;否则返回空值(其实也是var的值)

${var:?newstring}  如果var未定义或为空值,则将newstring写入标准错误,本语句失败;否则返回var的值

脚本的特殊变量

$0:当前脚本的文件名/当前执行的进程/程序名

$n:n为从1开始的数字,$1是第一个参数,$2是第二个参数,${10}是第十个参数(从${10}开始参数号需要用花括号括起来)

$#:传入脚本的参数的个数

$*:所有的位置参数(作为单个字符串)

$@:所有的位置参数(每个都作为独立的字符串)。

$?:当前shell进程中,上一个命令的返回值,如果上一个命令成功执行则

$? 的值为0,否则为其他非零值,常用做if语句条件

$$:当前shell进程的pid

$!:后台运行的最后一个进程的pid

 

本节课任务

创建脚本文件:varstudy.sh

赋予可执行权限

脚本运行时输出参数个数

并输出参数个数,以及程序的名称和参数字符串

显示当前工作目录以及用户主目录

 

第十二章 shell脚本基础-逻辑判断与循环

Test

test是shell内建命令,可以处理脚本里的各类工作,产生的不是一般形式的输出,而是可用的退出状态。使用help test查看帮助文档。

test命令有其他形式:[······],[[······]]。当在[ ]中使用&&|| 会出错,这时候要使用[[ ]]。

test返回true或false,但是test返回的true是0,false是1,这和通常的编程语言定义的true是1(或非0值),false是0有所区别。(Linux/Unix上程序退出 状态为0表示0错误正确执行,而非0值表示有错。)

例:test “abc”=“abc” ; test -f ~/tmp/a.sh ; [-f ~/tmp/a.sh ]

If,else,elif

if ,else,elif的语法结构:

写在一行要使用分号分隔:if [COMMAND] ; then [COMMAND] ;fi

示例:

if ,else,elif的用法:

file=~/sh/a.sh

dbin=~/bin

if test -f“$file” ; then

    cat “$file”

elif [ -d“$dbin” ] ; then

    ls “$dbin”

else

    echo “file not found”

fi

if [[ -f “sh/a.sh” && -f “sh/h.sh”]] ; then cat sh/a.sh sh/h.sh ; fi


case

多个判断值可以使用if,elif,else组合。更简洁的形式是使用case语句实现, 就像普通编程语言的switch。语法结构:

case WORD in

    VALUE1)

        [COMMANDS] ;;

    VALUE2)

        [COMMANDS] ;;

    *)

        [COMMANDS]

        ;; //esac之前的;;可以省略

Esac

• )是必须要加的,每个逻辑块执行到;;结束。*)是默认情况,并非必须。

示例:

创建shell脚本casetest.sh,写入一下代码并运行:

case $1 in

“hello”)

        echo “hey!”

        ;;

“time”)

        Date

        ;;

*)

echo “nothing to do”

esac

选项可以写成不带引号的形式:time hello

For

for循环用于重复整个列表对象,基本用法

 forNAME in WORDS; do COMMANDS; done

for NAME in WORDS

do

    COMMANDS

Done


While与until

while与until循环的结构一致,不同的是对待条件退出的状态,while是 成功则执行,until是不成功则执行。结构使用如下:

while CONDITION; do #do写在单独一行,;可以不写

    COMMANDS

done


本节课任务

在当前用户主目录创建bin目录(如果bin目录不存在)。

在bin/创建脚本文件pse

要求脚本运行时检测参数个数是否>0,大于0则使用第一个参数作为筛选条 件。否则直接运行ps -e -ouser,pid,ppid,tty,comm,args

 

第十三章 Vim和Linux C编程环境

vim配置文件

安装vim后,配置文件:/etc/vim/vimrc, vim启动时会读取此文件。除此之 外,在用户主目录下如果存在.vimrc,也会读取此文件,如果存在相同的配置,则.vimrc文件配置会覆盖/etc/vim/vimrc的配置。

/usr/share/vim/vim74/colors是vim的配色主题文件所在目录,在用户主目录 下的.vim/colors也可以保存主题文件,此目录通常需要自己创建。

通用的配置可以写在/etc/vim/vimrc,个性化设置可以放在~/.vimrc

vim配置文件使用 ” 标记注释。

基本配置

set mouse=a “ 启用鼠标支持,a表示所有模式都支持

set t_Co=256  “ 256颜色支持

set number “ 显示行号

set backspace=2 “ 设置退格键删除

set fileencodings=utf-8 “设置写入文件编码为

utf-8 set encoding=utf-8 “ 设置vim缓冲区编码utf-8

set termencoding=utf-8 ” 设置终端显示编码为utf-8

set autoindent “ 自动缩进

set shiftwidth=4 “缩进4空格宽度

set tabstop=4 “ tab缩进4空格宽度

set expandtab “ tab转换为空格

颜色主题配置

设置暗色背景和暗色主题

setbackground=dark

colorschemetomorrow-night

设置亮色主题和亮色背景

setbackground=light

colorschemetomorrow

gcc基本介绍与安装

gcc不是一个软件,全名是GNUCompiler Collection,是一个编译器 集合。

gcc支持C, C++,Objective-C, Fortran, Ada, Go语言的编译。

gcc是GNU的一个项目,发布于GPL开源协议。

UbuntuServer版本都自带gcc,如果没有则运行: sudo apt install gcc。

gcc基本使用

使用vim test.c创建文件并编写一段C程序。

gcc test.c即可编译,编译后的文件是a.out。

./a.out运行编译的程序。

gcc编译后的默认名称是a.out

gcc –o test test.c :编译后的文件是test,-o参数后面跟输出文件的名称。

ELF文件

gcc test.c编译后的输出文件是ELF格式的。

而扩展名和文件类型并没有关系,Windows是设计必须使用扩展名和对应的运行程序去关联。Windows上采用的PE格式作为可执行文件格式,.exe是 Windows上的可执行文件的扩展名。

在Linux上采用的ELF格式不必在文件名中体现出来。但是如果使用vim打开 编译后的文件,在最开始会看到ELF三个字符表明是ELF文件。

readelf -h ./test可以查看test程序的ELF文件头信息。

glibc

glibc是Linux上标准C的函数库实现。

.so文件是Linux上的共享库文件,相当于Windows上的.dll文件。

glibc的实现库文件是/lib/x86_64-linux-gnu/libc.so.6链接到 /lib/x86_64-linux-gnu/libc-***.so;星号表示版本,比如,在 UbuntuServer16.04上是2.23,UbuntuServer18.04上是2.27。

gcc在编译C语言代码的时候要用到glibc。

main函数的参数和返回值

int main (int argc, char* argv[]) { /* ………… //something code */ return 0; }

main函数的返回值是程序的退出状态表示程序是否正确执行。

argc是传递给程序参数的个数,argv是每个参数的值,argv[0]永远都是程序文件的名称。但是这个名称是带有路径信息的。

支持参数的程序

输出传递给程序的参数:

#include <stdio.h>

int main(int argc, char* argv[]) {

    printf(“programname: %s\n”, argv[0]);

    for (int i=1;i<argc; i++)

        printf(“%s ”, argv[i]);

    if (argc>1)

        printf(“\n”);

    return 0;

}

编程训练

编写一个对整数排序的程序,通过参数获取数字,并输出排序结果。

使用插入排序即可,插入排序示例(nms是数字数组):

int k,j,tmp;

for (k=1;k<N;k++) {

    tmp = nms[k];

    for(j=k;j>0&& nms[j-1]>tmp;j--)

    nms[j] = nms[j-1];

    nms[j] = tmp;

}

提示: 通过atoi(argv[i])可以把输入的参数转换成整数。 int *n = (int*)malloc(sizeof(int)*10);会申请一个长度为10*sizeof(int) 字节的数组,并返回一个int*类型的指针。使用free(n)释放掉申请的内存。

 

第十四章  Linux系统编程基础

系统编程简介

系统编程就是调用Linux系统提供的API完成需要的任务。

Linux上的大多数命令都是用C编写的,多数都需要用到系统调用。

man 2 [system call name]查看系统接口文档,man  3  [libfunction] 查看程序 库函数的文档。文档开头都会说明需要引入的头文件,函数声明等信息。

man syscalls查看所有系统调用(API)。

本次课程讲解基本的系统调用,主要包括获取进程ID,fork创建子进程, open,write,close操作文件,IO重定向如何实现等内容。

获取自己的PID

系统调用:pid_t getpid();

示例:

#include<stdio.h>

#include<sys/types.h>

#include<unistd.h>

int main(intargc, char *argv[]) {

    printf(“%d\n”, getpid() );

    return 0;

}

用fork创建子进程

系统调用:pid_t fork();

fork会创建子进程,调用fork,新创建的进程会和父进程一样继续执行。

fork出错返回-1并且不会创建新的进程;正确则在父进程返回创建子进程的PID,在子进程返回0。

由于父进程和子进程不同的返回值。可以通过判断返回值控制父进程和子进程执行不同的代码。

等待子进程退出

系统调用:pid_t wait(int *status);

wait等待子进程退出,并把子进程退出状态设置到status变量。返回退出进程的PID。

wait调用会挂起父进程,直到子进程退出。

类似的调用还有pid_t waitpid(pid_t pid, int *status, int options);详细说明可在终端运行man 2 waitpid查看。

wait调用相当于调用waitpid(-1, &status, 0);

父进程先于子进程退出,子进程被init进程接管

父进程退出后,子进程继续执行,此时父进程是init(ID为1的进程)。而在终端运行程序,当前shell是父进程的父进程,但是由于父进程的提前退出,导致子进程被init进程接管。

这是Linux的设计方式,并且此方式是实现守护进程的基础。

Open函数

open函数用于打开文件操作:

int open(constchar *pathname, int flags, mode_t mode); 参数依次为文件路径名称,标志位,模式。成功返回值为打开的文件描述符,错误返回-1。

flags选项:

O_CREAT       没有则创建文件

O_WRONLY   写模式打开文件

O_RDONLY    只读模式打开文件

O_RDWR        读写方式打开

mode选项:

S_IRWXU        文件所有者具有可读,可写,可执行的权限

S_IRUSR         文件所有者有可读权限

S_IWUSR        文件所有者具有可写权限

Write函数

write函数向一个文件写入数据:

ssize_twrite(int fd,  const void *buf, intcount);

参数依次为打开的文件描述符,指向数据的指针,要写入的字节数。

返回值是成功写入的字节数,错误则返回-1。

在文件操作最后要记得使用close关闭打开的文件:int close(int fd); close函数成功返回0,错误返回-1。

IO重定向

IO重定向基于这样一个设计原则:最低可用文件描述符(Lowest Availablefd)原则。

文件描述符是一个数组索引号,每个进程都有一组打开的文件,这些打开的文件信息保存在一个数组中,文件描述符就是数组的索引号。

在打开文件时,分配的描述符总是数组中最低可用的索引位置(索引数字最小的位置)。

在Linux上,使用0,1,2作为程序的标准输入,标准输出,标准错误输出。而如果关闭描述符1,然后打开其他文件,这样文件就被分配了文件描述符1,于是标准输出就会写入到新打开的文件。这就是IO重定向。

IO重定向实现方法

编程实现的方式(以文件描述符1为例):

close-open-close方式,先close(1),然后open(filename, O_RDWR, S_IWUSR); 操作完成,close关闭新打开的文件。

open-close-dup-close方式,open打开文件,返回的文件描述符不是1,然后 close(1),现在最低可用描述符是1,dup(fd)会把新打开的描述符复制到1,然后 close(fd)关闭新打开的文件。

open-dup2-close方式,dup2(oldfd, newfd),关闭newfd,把oldfd复制到newfd,close关闭新打开的描述符。

编译运行c文件

将源文件保存为hello.c,开始进行编译(如hello.c文件)

$gcc -o hello hello.c

编译成功完成后,在当前路径下,生成一个名为hello的文件,然后执行

$./hello

第十五章 Linux系统调用:IO

open函数

open函数用于打开文件操作:

int open(const char*pathname, int flags, mode_t mode); 参数依次为文件路径名称,标志位,模式。成功返回值为打

开的文件描述符,错误返回-1。

flags选项:

O_CREAT      没有则创建文件

O_WRONLY    写模式打开文件

O_RDONLY    只读模式打开文件

O_RDWR      读写方式打开

mode选项:

S_IRWXU      文件所有者具有可读,可写,可执行的权限

S_IRUSR       文件所有者有可读权限

S_IWUSR      文件所有者具有可写权限


close函数

在文件操作最后要记得使用close关闭打开的文件:int close(int fd);

close函数成功返回0,错误返回-1。

read函数

read函数从一个文件读取数据:

ssize_t  read(int fd,  const void *buf, int count);

参数依次为打开的文件描述符,指向数据的指针,要读取的字节数。

返回值是成功读取的字节数,如果有错误则返回-1。


write函数

write函数向一个文件写入数据:

ssize_t write(int fd,  const void*buf, int count);

参数依次为打开的文件描述符,指向数据的指针,要写入的字节数。

返回值是成功写入的字节数,错误则返回-1。


IO重定向

IO重定向基于这样一个设计原则:最低可用文件描述符(Lowest Availablefd)原则。

文件描述符是一个数组索引号,每个进程都有一组打开的文件,这些打开的文件信息保存在一个数组中,文件描述符就是数组的索引号。

在打开文件时,分配的描述符总是数组中最低可用的索引位置(索引数字最小的位置)。

在Linux上,使用0,1,2作为程序的标准输入,标准输出,标准错误输出。而如果关闭描述符1,然后打开其他文件,这样文件就被分配了文件描述符1,于是标准输出就会写入到新打开的文件。这就是IO重定向。


IO重定向实现方式

编程实现的方式(以文件描述符1为例):

close-open-close方式,先close(1),然后open(filename,

O_RDWR, S_IWUSR); 操作完成,close关闭新打开的文件。

open-close-dup-close方式,open打开文件,返回的文

件描述符不是1,然后 close(1),现在最低可用描述符是1,

dup(fd)会把新打开的描述符复制到1,然后 close(fd)关闭新

打开的文件。

pen-dup2-close方式,dup2(oldfd, newfd),关闭newfd,

把oldfd复制到 newfd,close关闭新打开的描述符。

练习

编写一个简单的复制命令:接受两个参数,第一个参数作为要复制的文件,第二个参数是要复制的文件名。

第十六章 系统服务

系统服务的特点

系统服务程序和在shell运行的普通命令不同,如果在shell运行一个命令,shell是作为父进程fork出子进程去运行的。

而系统服务程序运行后往往是守护进程(daemon process),守护进程是作 为init进程(进程ID为1的进程,init负责系统的初始化)的子进程,并且不会连接到终端,输入输出都不会经过终端。

系统服务程序开机后会启动,并运行在后台,提供基本的服务支持。(当然也是可以开机启动完成任务后退出,并没有严格限制,但多数系统服务程序都要在后台运行。)

系统服务管理命令:service

service  --status-all显示所有的服务。

使用示例:service  ufw restart

也可以直接运行脚本文件:sudo /etc/init.d/networking restart

系统启动初始化脚本(init scripts)

/etc/init.d是系统服务的启动程序,一般都是脚本程序。长期运行的服务进程通常是脚本程序去调用指定的程序运行。

但是系统启动并不会直接启动这个目录下的服务程序。

原因在于Linux系统有运行级别的问题,每个启动级别运行的服务是不同的。Linux在启动时会根据配置文件设置的启动级别查找相对应的目录启动程序。

系统运行级别

Linux系统有7个运行级别:

0:关机,默认级别不能是0,否则不能正常启动

1:单用户模式,用于系统维护,不能远程登录

2:多用户模式,不支持NFS

3:多用户模式,支持NFS

4:系统保留,未定义

5:界面模式,开机后进入桌面环境

6:重启,默认运行级别不能是6否则会不断重启

查看运行级别的命令:runlevel

系统运行级别所对应的/etc/rc*.d目录

Linux如何让每个运行级别对应不同的系统服务?

/etc/存在rc*.d 目录,*是0-6的数字, /etc/init.d目录下的服务程序只是一个集合,系统启动时,会根据级别运行rc*.d目录的程序,而此目录下是链接到/etc/init.d的符号链接,这样就实现了不同级别的不同服务配置。

注意这里有rc0.d和rc6.d,这两个目录下的符号链接是K开头,而其他的是S开头,K开头的是不启动的,而是在离开此运行级别时要进行的操作,比如关机要进行一些清理工作。

符号链接S/K后面跟的数字是启动顺序,数字小的先运行。

添加一个自己的脚本

如果要添加自己的服务脚本,把文件放到/etc/init.d目录,在对应的启动级别的rc*.d录都要创建符号链接到/etc/init.d目录下的文件即可。

例:有服务脚本sh/servtest,通过runlevel查看启动级别是5,把 servtest复制到/etc/init.d,然后创建符号链接:

sudo cp  sh/servtest/etc/init.d/

sudo ln -s /etc/init.d/servtest /etc/rc5.d/S05servtest


©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

SevenZS

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值