shell常见问题

常见的命令:

less less 文件名,q退出;可以查看文件内容 和cat -A filename很像
cat cat 文件名,打印文件内容,可以打开多个文件 cat file1 file2
grep -参数 文件名
-i 不区分大小写
-r +“关键字” +file 。迭代文件查找关键字并输出
-c +“关键字” +file 。输出含有关键字的行数
-n +“关键字” +file 。列出所有的匹配行,并在最前面添加行的序列数
-l +“关键字” +./* 。 查找出所有包含关键字内容的文件
-x +“关键字” +file1 (file1 file2) 。完全匹配输出,比如:grep -x hello a.txt,只会输出某一行存在hello字符串,并且此行仅包含hello的内容。假设a.txt中有一行“hello all”,执行上述命令,此行不会被搜索到。

wc -参数 文件名。 用于统计文本大小,字符多少 行数
-c 字节数 -m 字符数 -l 行数

sort -参数 文件名 。排序
sort -t+域分隔符 + k1(k2\k3…) + file
这样就能够根据某个字段来进行排序,比如排序一下内容

a=1
b=22
c=333
d=23
f=19
efa=13
fdia=311
diwk=281
在这里插入图片描述
此处的k2就是按照第二个域来排序。如果不设置-t= 那就自动按照顺序字符来排序。

| 管道,把上一条命令的结果传输给下一条命令

> >> >相当于 w模式,清空文件并写入 。 >> 相当于 a 模式,追加写入文件。重定向。

awk 可以写成代码的形式,样式很多
举一些例子 awk ‘{print $1" "$2}’ Dockerfile 输出每一行的第一个和第二个字符
cat -A Dockerfile.bak |xargs -n 1|sort |uniq -c |sort -nr|awk ‘{print $2}’

ps -aux 显示所有包含其他使用者的行程
-a 显示所有终端机下执行的进程
ps -p 2 -o pcpu|grep -v CPU 获取某个进程的cpu使用情况

echo 出$? 其他的一般写在脚本内部
echo $? 上个命令退出的状态
echo $0 当前脚本文件名
echo $n 传递给脚本的参数 $1 $2 第一个参数第二个参数
echo $$ 当前shell进程的ID。

检查系统资源使用情况

  1. free 查看内存占用情况
  2. top 查看系统整体负载
    下图中

第一行:系统时间 + 当前用户数 + 平均负载情况 1分钟/5分钟/15分钟
第二行:进程总数 + 正在运行进程数 + 睡眠进程数 + 停止进程数 + 僵尸进程数
第三行:用户空间cpu占比us + 内核空间cpu占比sy + CPU空置率id
第四行:内存状态,缓存的内存量
第五行:交换分区信息 这两行,可用内存=free+buffer+cached。内存监控主要监控交换区的used信息,如果这个数值一直变化就说明内存在和交换区
第六行: 进程id+进程持有者+进程优先级+nice值负值表示高优先级 +VIRT 进程使用虚拟内存总量 (VIRT=SWAP+RES) + RES 未被换出物理内存大小 + SHR 共享内存大小 + S表示进程状态(D不可中断睡眠、R运行、S睡眠、T跟踪\停止、Z僵尸) + %CPU 上次更新到现在CPU时间占用比 + %MEM 使用物理内存占用比 + TIME进程使用CPU总是时间数
图片
在这里插入图片描述
linux的交换区:linux为了提高读写的效率,会将文件在内存中缓存,这部分就是cache memory。即使程序运行结束之后,这部分缓存也不会被释放,因此当有非常频繁的文件读写时就会导致可用的物理内存变小。当系统物理内存不够用的时候,就会把一些空间释放,这些空间的内容就被存入swap空间中,如果后面又用到了这些内容,就会从交换区中取出。 因此,只有当物理内存不够用的时候,交换区的大小才会不断变化。
其实linux的交换区比较像windows上的虚拟内存,都是为了解决物理内存不够的策略,实际上就是利用磁盘空间虚拟出一块逻辑内存。内核会把物理内存中不常用的数据块交换到虚拟内存中。交换的策略是最近最经常使用算法lru。

cached和buffer的区别
cached是cpu与内存间的,buffer是内存与磁盘间的,都是为了解决速度不对等的问题。
方便理解可以这么看buffer是当不同的进程写入磁盘的时候,有快有慢,buffer就把快的先记录下来,进程就可以去做其他事情了;而cached是cpu要经常访问一个文件的内容,于是就把这些内容一致放在cached里面,这样下一次cpu去访问这个 访问这个文件内容的时候就不用再去读取。

缓存(cached)是把读取过的数据保存起来,重新读取时若命中(找到需要的数据)就不要去读硬盘了,若没有命中就读硬盘。其中的数据会根据读取频率进行组织,把最频繁读取的内容放在最容易找到的位置,把不再读的内容不断往后排,直至从中删除

缓冲(buffers)是根据磁盘的读写设计的,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。linux有一个守护进程定期 清空缓冲内容(即写入磁盘),也可以通过sync命令手动清空缓冲。举个例子吧:我这里有一个ext2的U盘,我往里面cp一个3M的MP3,但U盘的灯 没有跳动,过了一会儿(或者手动输入sync)U盘的灯就跳动起来了。卸载设备时会清空缓冲,所以有些时候卸载一个设备时要等上几秒钟

查看打开的端口,进程打开文件

lsof -i:端口号
lsof -i tcp
lsof -i tcp:端口

lsof file 查看谁在用某个文件
lsof -u username 打开某个用户打开文件信息
lsof -p pid 查看端口号打开文件信息

用户命令

useadd -g test -d /home/test(登录时的主目录) -s /bin/bash(登录后自动使用的shell) -m 自动登录目录

查看用户组 cat /etc/group cat /etc/passwd

根目录下各个文件

  1. /boot 引导程序,内核等存放的目录.
    包含了引导过程中所必须的文件。启动的时候,通过引导程序将内核加载到内存,完成内核启动。

  2. /sbin 超级用户使用命令的存放目录,必须要root权限啦

  3. /bin 普通用户可以使用命令的存放目录,如ls\cp\mkdir这些命令, 类似的目录还有 /usr/bin 和/usr/local/bin 这些目录的文件都是普通用户可以执行的命令

  4. /lib 根目录下所有程序共享库的目录

  5. /dev device,就是设备文件目录

  6. /home 普通用户的根目录

  7. /etc 全局配置文件存放目录
    系统和程序都有一些对应的配置文件,比如要配置系统开机启动那些程序,还有用户数据库啊这些。
    /etc下细分,可以分为很多,常见的
    /etc/passwd 用户数据库
    /etc/group 用户组信息

  8. /usr 存放一些安装程序信息
    /usr/lib 一些动态链接库文件
    /usr/bin 使用者使用并且不是系统自检的可执行文件目录
    /usr/local 安装本地程序默认路径
    /usr/include C语言编译的头文件目录

  9. /proc 一些进程信息文件

fork函数

所有的进程都是从pid为0的进程通过系统调用fork生成的。

  1. fork函数

pid_t fork(void);

这个函数没有参数,但是他的返回值却能返回两次。
fork的返回值是pid_t 类型,他就是通过typedef定义的一个32位的有符号整型数。不同的返回值代表了不同的身份。

>0 :就是本身,就是父进程,返回值代表着fork出来的子进程的pid号
=0 :就是子进程
=-1:失败

测试代码

#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
int main(){
        char buf[]="i am father process\n";
        write(STDOUT_FILENO,buf,strlen(buf));
        printf("before fork\n");         
        pid_t pid=fork();
          
        if(pid==0){ 
                printf("iam child process pid:%d, my father is pid:%d\n",getpid(),getppid());
                sleep(2);
        }
        else if(pid==-1){
                printf("error");
                sleep(2); 
        }
        else{
                printf("iam father process pid:%d, my child is pid:%d\n",getpid(),pid);
                sleep(2);
        }
        return 0; 

}

返回的结果,可以看到父进程用getpid得到自己的id,pid从fork函数得到子进程的id;
而子进程用getpid得到自己的id,用getppid得到父进程的id
在这里插入图片描述
2. 进程空间
参考:https://blog.csdn.net/q1007729991/article/details/53728757
这里的进程空间,说的就是虚拟地址空间。
每一个进程在创建的时候都分配了4GB的虚拟地址空间。
有个例子展现虚拟地址的特点,进程A往0x50000000 写入一个int类型的数字100,进程B往0x50000000 写入了另一个整数1000,然后两者都用printf函数输出,发现两个进程都顺利的打出了100、1000自身的数值。
形成上面结果的原因是进程A和进程B的地址空间是隔离的,尽管他们都是写在同一个位置,但是实际上这些位置都是他们自己的位置,如下图。

在这里插入图片描述
从虚拟地址到物理地址的映射
可能会很好奇是什么方式实现了以上的效果。好像有一只无形的手控制了我们写入的地址。实际上就是采用了地址映射的方式。继续用菜地比喻的话,就是我和我弟弟有一个管家,管家和我们说,我们每个人都有15块地(大部分情况下我们都不会种满,因此实际上可能一共只有20块地),管家设置了一个映射表,我们每次吩咐管家种地,管家在我这边汇报了种在某一块地上,实际上只是在本子上记录种在那块地上,真正种的地方是20块地中的一个位置。这个映射的过程需要一个映射表来记录。
在这里插入图片描述

  1. fork和进程空间
    我们知道fork会复制一个和父亲一样的子进程。那么内核的做法就是创建一个一模一样的进程空间,而且父进程和子进程虚拟空间映射到物理地址是同一个地方。这么做的原因也很好理解,因为大部分情况子进程不会对父进程的大部分东西进行修改,如果在物理地址空间重新复制一个,那么效率上就降低了很多。
    在这里插入图片描述
    内核这么做了,那如果其中一个进程想要对虚拟地址上的内容进行修改该怎么办呢?肯定不能把另一个进程的东西也改了吧。
    这时候就用到了写时复制技术,写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个地址空间,而是让父进程和子进程共享一个拷贝。只有在需要写入的时候,数据才会复制,从而使各个进程拥有各自的拷贝。
    写时复制技术

  2. 理解最后一个点,用户空间和内核空间
    上面谈到fork会创建一个相同的虚拟空间共享一个物理地址空间,那么如果fork前打开了一个文件,fork之后文件描述符是共享的吗。
    实际上4GB内存空间不是完全隔离的,32位linux,0-3GB是用户空间,3-4GB是内核空间,对于一个进程他是无法修改内核空间的,因此写时复制技术在内核空间上也就无用了。
    在这里插入图片描述

除了打开的文件外,父进程的很多其他性质也会被子进程共享,比如各种 ID 号、当前工作目录、根目录、资源的限制、信号屏蔽字、进程环境、文件打开执行时关闭标志、共享存储段。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值