1. 程式人生 > >馬哥教育第三十一天至三十四天學習總結

馬哥教育第三十一天至三十四天學習總結

內核編譯、系統開機、系統進程管理、AWK

馬哥M28三十一天、

進程管理和啟動流程、

CentOS6及其之前的操作系統根進程是/sbin/init , centos5及其之前使用的安裝管理工具是SysV ,CentOS6是upstart , CentOS7是systemd

單用戶方式啟動:修改root密碼或者跳過異常服務快速啟動系統; 啟動菜單選擇內核 a鍵進入編輯 rhgb quiet 後面加 1 -->esc ,b

給grub加密,不用明文。

grub-crypt >> /boot/grub/grub.conf :grub-crypt 采用是sha512加密的方式,md5不安全
在第一個title上面加上,應該在hiddenmenu行之上加上;

password --encrypted $1$d/YOm/$V6YVIw8YEs9ik.gSj/bfx1

1:加電到bootloader加載

系統加電,BIOS(基本輸入輸出系統)代碼裝載入內存

一:自檢,主要負責監測系統外圍關鍵設備(CPU、內存等)是否正常

1、根據配置的啟動設備(如harddisk、cdrom、網卡--pxe方式等)去讀區啟動代碼

    A:硬盤啟動:

     (1)BIOS會讀區硬盤第一個扇區的512Bytes中前446個字節bootloader代碼,我們拷貝出硬盤第一扇區的內容

                          dd if=/dev/sda of=mbrFile bs=512 count=1 && file mbrFile

[plain] view plain copy
#dd if=/dev/sda of=mbrFile bs=512 count=1 && file mbrFile
記錄了1+0 的讀入
記錄了1+0 的寫出
512字節(512 B)已復制,0.000177423 秒,2.9 MB/秒
mbrFile: x86 boot sector; GRand Unified Bootloader, stage1 version 0x3, 1st sector stage2 0x449fe, GRUB version 0.94; partition 1: ID=0xee, starthead 0, startsector 1, 4294967295 sectors, extended partition table (last)\011, code offset 0x48

MBR會保存有bootloader代碼,並且含有分區表記錄,主要記錄一些分區類型、是否是活動分區、分區跨度等信息。之後我們可以在分區上建立文件系統(常見的文件系統例如FAT、NTFS、EXT2、EXT3等等),俗稱格式化。
"硬盤的第一個扇區是MBR(512字節,512 字節=446(引導程序)+64(分區表信息)+2(結束標記)),如果有安裝grub,那麽接下來的31KiB (62扇區)是grub引導程序的位置,也就是說,要使用grub這樣的雙引導程序,硬盤的第一個分區至少要從63扇區開始,而一般情況下(默認),硬盤的第一個分區是從2048扇區開始",這裏63個扇區,其中第一個是MBR位置。

2.一、linux系統的啟動過程 bootloader 常見包含:LILO grub spfidisk

1.加載BIOS,上電自檢。因為BIOS中包含了CPU的相關信息、設備啟動順序信息、硬盤信息、內存信息、時鐘信息、PnP特性

 等。通過BIOS的設置,計算機就知道去讀取哪個硬件設備了。

2.讀取MBR,即主引導記錄(註意:MBR不屬於任何分區,所以使用grub-install修復boot loader即當前的grub時指定的一定是整塊系統盤 /dev/sda)。(這裏有幾個MBR中概念:DPT:分區表,通俗說就是硬盤上記錄分區信息的表。PBR:硬盤分區

 引導記錄,就是具體到某個分區時,上邊記錄著這個分區的一些信息,詳細了解可度娘。)它的大小是512字節,裏面存放了預

 啟動信息、分區表等信息。系統找到BIOS所指定的硬盤的MBR後,就會將其復制到0×7c00地址所在的物理內存中。其實被復制

 到物理內存的內容就是Boot Loader,而具體到你的電腦,那就是lilo或者grub了。

3.Boot Loader。Boot Loader 就是在操作系統內核運行之前運行的一段小程序。通過這段小程序,我們可以初始化硬件設備、建

 立內存空間的映射圖,從而將系統的軟硬件環境帶到一個合適的狀態,以便為最終調用操作系統內核做好一切準備。Boot Loader

 有若幹種,其中Grub、Lilo和spfdisk是常見的Loader。要了解GRUB的,可自行查閱資料。

4.Boot Loader加載內核,加載initrd。到此,這是本文要著重說明的地方。

關於GRUB:

grub引導也分為兩個階段stage1階段和stage2階段(有些較新的grub又定義了stage1.5階段)。
1)、stage1:stage1是直接被寫入到MBR中去的,這樣機器一啟動檢測完硬件後,就將控制權交給了GRUB的代碼。也就是上圖所看到的前446個字節空間中存放的是stage1的代碼。BIOS將stage1載入內存中0x7c00處並跳轉執行。stage1(/stage1/start.S)的任務非常單純,僅僅是將硬盤0頭0道2扇區讀入內存。而0頭0道2扇區內容是源代碼中的/stage2/start.S,編譯後512字節,它是stage2或者stage1_5的入口。而此時,stage1是沒有識別文件系統的能力的。如果感覺腦子有些暈了,那麽下面的過程就直接跳過,去看stage2吧!
【外傳】定位硬盤的0頭0道2扇區的過程:
BIOS將stage1載入內存0x7c00處並執行,然後調用BIOS INIT13中斷,將硬盤0頭0道2扇區內容載入內存0x7000處,然後調用copy_buffer將其轉移到內存0x8000處。在定位0頭0道2扇區時通常有兩種尋址方式:LBA和CHS。如果你是刨根問底兒型的愛好者,那麽此時去找谷哥打聽打聽這兩種方式的來龍去脈吧。
2)、stage2:嚴格來說這裏還應該再區分個stage1.5的,就一並把stage1.5放在這裏一起介紹了,免得大家看得心裏亂哄哄的。好的,我們繼續說0頭0到2扇區的/stage2/start.S文件,當它的內容被讀入到內存之後,它的主要作用就是負責將stage2或stage1.5從硬盤讀到內存中。如果是stage2,它將被載入到0x820處;如果是stage1.5,它將被載入到0x2200處。這裏的stage2或者stage1_5不是/boot分區/boot/grub目錄下的文件,因為這個時候grub還沒有能力識別任何文件系統。
? 如果start.S加載stage1.5:stage1.5它存放在硬盤0頭0道3扇區向後的位置,stage1_5作為stage1和stage2中間的橋梁,stage1_5有識別文件系統的能力,此後grub才有能力去訪問/boot分區/boot/grub目錄下的 stage2文件,將stage2載入內存並執行。
? 如果start.S加載stage2:同樣,這個stage2也不是/boot分區/boot/grub目錄下的stage2,這個時候start.S讀取的是存放在/boot分區Boot Sector的stage2。這種情況下就有一個限制:因為start.S通過BIOS中斷方式直接對硬盤尋址(而非通過訪問具體的文件系統),其尋址範圍有限,限制在8GB以內。因此這種情況需要將/boot分區分在硬盤8GB尋址空間之前。
假如是情形2,我們將/boot/grub目錄下的內容清空,依然能成功啟動grub;假如是情形1,將/boot/grub目錄下stage2刪除後,則系統啟動過程中grub會啟動失敗。

1.確定服務器的boot文件系統所在分區是哪塊硬盤上的,首先在rescue模式下切換到正確的操作系統的根目錄,然後使用grub-install /dev/sda 修復完成後,在此過程中需要註意的是可能會出現一些不能修復的bug, 是否完全完成後一定要sync同步一下,多sync幾次

root (hd0,0) :說明,root是根的意思,此處就是指明(hd0.0)是根,而此第一塊硬盤的第一個分區在實際自己的操作系統上就是/dev/sda1,對應就是掛在到/boot下,所以下面的"/"就是boot,而如果在安裝操作系統的時候boot本身並沒有獨立分區,而是在根文件系統下,所以下面的使用必須相對於boot路徑 kernel /boot/vmlinuz....
kernel /vmlinux.... ro root=/dev/sda2
initrd /initramfs....

#註意:如果/boot/initramfs$(uname-r)文件遭到破壞,在沒有使用mkinitrd修復生成前重啟計算機導致失敗,必須進入rescue救援模式,使用mkinitrd工具生成
mkinitrd /boot/initramfs-$(uname -r) $(uname -r ) 最後參數應該指定準確的內核版本,並且生成的映像文件(.img)必須也是(initramfs-$(uname -r).img),格式必須準確

centos5
/boot/grub/grub.conf
/etc/inittab ---> /etc/rc.d/rc.sysinit---> /etc/fstab
---> /etc/sysctl.conf
---> /etc/rc.d/rc
---> /etc/rc.d/rcX.dge 2 /initramfs-$(uname -r).img 需要掛載/dev/sda2前提是有ext4.ko
--> /etc/rc.d/rcX.d/K.. S..
--> /etc/rc.local

重要:1.對系統重要配置文件以及腳本文件進行學習,理解邏輯思維和編程方式,進而可以詳細理解系統以及服務運行;
2.學習其腳本,進行改良或者自行編寫!!!
3.修改當前運行級別下的開機啟動服務狀態圖形化工具: ntsysv; 命令行工具:chkconfig --level 2345 atd off/on
4.開機服務都在/etc/init.d/ ,對應的是當/etc/rc.d/rc.sysinit讀取執行後,將運行級別傳遞參數給/etc/rc.d/rc,並且同時在/etc/rc#.d/.conf以及此目錄下的所有對應的當前運行級別開機啟動與關閉的服務都是軟連接到/etc/rc.d/下的實際服務;開機服務S*,對比單個字符acs碼大小進行排序(不是按照數字序號排),後啟動的是高層次程序,依賴底層多,也應該先關閉;

第三十二天、

系統排錯恢復;重點,強化練習實踐

1.切記:在救援模式下,一定要chroot到指定目錄/mnt/..,不能將文件掛載到rescure模式的根下!!
2.在命令界面下來回上下切換 shift+pageup shift+pagedown
3.[root@magedu 2018-03-26 functions]# blkid |grep sda2
/dev/sda2: UUID="f582fb22-c0bc-4fee-b42c-0c7c41708a65" TYPE="ext4" 在救援自主編寫/etc/fstab時,必須將雙引號去掉; 在選擇內核的時候,在quiet後加 selinux=0

4.非常重要:在定位到了具體的文件是損壞了或者丟失了,1.rpm -qf /bin/filename ; 2.必須使用cp 到指定目錄後,然後rpm2cpio filename |cpio -id 進行格式轉換成cpio後在解壓並生成指定目錄,然後進入到想要指定的文件目錄下拷貝指定損壞文件到指定位置!
:原則,針對問題定位如果是具體的文件的問題,通過rpm -qf filename來進行查找安裝包,最小原則,rpm2cpio filename |cpio -id來進行恢復,拷貝包中具體單個文件進行恢復,不破壞其他文件配置

5.CentOS7中,救援模式選擇 troubleshoot --> 檢索修復/boot目錄下的文件->grub2-install; 生成內核映像文件 initramfs-$(uname -r).img $(uname -r)

6.裝載X11圖形化界面:主要安裝包組(yum grouplist 查出X windows .. 以及其他包組)

系統啟動流程

進一步說明stage1 stage1.5 stage2 grub.conf:
因為stage1是直接寫入到mbr中的,所以首先沒有識別文件系統的能力,但是mbr不在任何分區中,所以當bios中斷尋址硬盤的時候,mbr就可以將控制權直接交給boot loader即grub;
stage2是為了去讀取/boot/grub/grub.conf,但是此時依然沒有識別文件系統的能力,所以,stage1.5被stage1加載到內存中,在文件系統層抽象,stage1.5具有識別文件系統的能力,所以grub讀取boot分區的sector上的stage2,這種情況下刪除/boot/grub/stage2文件系統也能啟動,但是如果是直接讀取/boot/grub/stage2文件到內存,在沒有stage2文件的時候是不能正常啟動的(在rescue模式中重新安裝grub此stage2文件也是必須使用的了)

post
stage 1 mbr
stage 1.5 grub
stage 2 /boot/grub/grub.conf
kernel
initramfs
/sbin/init
/etc/inittab
id:3:initdefault:
/etc/rc.d/rc.sysinit
/etc/fstab
/etc/rc3.d/rc
/etc/rc.d/rc3.d/S*
/etc/rc.d/rc.local
mingetty tty1-tty6
init5 X11

  1. rm -rf /boot/grub/除grub.conf以外的所有文件,仍然可以啟動

  2. dd if=/dev/zero of=/dev/sda bs=1 count=446 破壞grub
    rescue
    chroot /mnt/sysimage
    grub-install /dev/sda

    kernel /vmlinuz.... ro root=/dev/sda2 selinux=0

vim /etc/selinux/config
SELINUX=disabled
恢復 hhaaa

3.rm -rf /boot/grub/除grub.conf以外的所有文件,ERROR 15無法啟動
cp /app/grub/stage2 /boot/grub

4.dd if=/dev/zero of=/dev/sda bs=1 count=10240 seek=512
rescue
chroot /mnt/sysimage
恢復/boot/grub/的Stage文件 一:從備份 二:grub-install
grub
root(hd0,0)
setup (hd0)

convert -resize 640x480 -colors 14 mage.jpg mage.xpm

post
mbr
stage 1 446
stage 1.5 root(hd0,0)
stage 2 kernel vmlinuz
init
....
rc.local

rhgb: 默認圖形化啟動
quiet: 啟動過程不顯示內核信息

/boot
vmlinuz-
initrd
grub/starge1 1_5 2 grub.conf

1.dd if=/dev/zero of=/dev/sda bs=1 count=446
stage 1階段:grub-install
2.dd if=/dev/zero of=/dev/sda bs=1 count=10240 seek=512
stage 1.5階段:grub-install
3.rm -rf /boot/grub/* stage 1.5 2:grub.conf

4.rm -rf /boot/* stage 1.5 2

實驗:刪除/etc/fstab及/boot下所有文件
a.進入Rescue,臨時將/dev/sda2掛載到臨時目錄,然後編寫/etc/fstab
b.重新進入Rescue,grub-install /dev/sda
c.編寫grub.conf

1.恢復/etc/fstab :通過rpm -qf /etc/inittab來找到安裝的包,然後通過rpm2info轉換並解壓,找到具體此文件進行復制到指定位置
如果根在LVM上,則先執行vgchange -ay,再掛載,將根臨時觀察法到臨時目錄,然後編寫/etc/fstab
2.重啟進入rescue,grub-install恢復/boot/grub目錄
3.mount /dev/cdrom /media ; rpm -ivh /media/Packages/kernel-2.6xxx.rpm
4.vim /boot/grub/grub.conf
title
kernel
initrd
5.rpm -qf /sbin/init
upstart...rpm
6.cp /media/Packages/upstart...rpm /var/tmp
rpm2cpio upstart...rpm |cpio -id
cp sbin/init /sbin

LFS

stage 1 mbr grub-install,分區表 fdisk
stage 1.5 grub-install
stage 2 grub-install grub.conf
/boot/vmlinuz /boot/initrd

bash
ls
ping
ifconfig
pwd

1.在現有的虛擬機當中加一塊硬盤20G,最好是單個磁盤文件。
2.如果當前虛擬機正在啟動 echo ‘- - -‘ > /sys/class/scsi_host/host0[2]/scan
3.fdisk /dev/sdb 分2個,一個100,一個10G
4.將/dev/sdb1 /dev/sdb2格式化為ext4文件系統
5.mount /dev/sdb2 /mnt; mkdir /mnt/boot ; mount /dev/sdb1 /mnt/boot
6.grub-install --root-directory=/mnt /dev/sdb
7.cp /boot/{vmlinuz-xxx,initramfs-xx.img} /mnt/boot
8.vim /mnt/boot/grub/grub.conf
kernel /vmlinuz... ro root=/dev/sda2 selinux=0 init=/bin/bash
9.mkdir -p /mnt/{etc,dev,proc,sys,home,var,mnt,media,root,tmp,lib,usr/{bin,sbin,lib,lib64}
10.利用復制命令及其lib文件的腳本復制基本命令至/mnt下,如bash ls ifconfig ping hostname cat vi mount umount mv touch cp modprobe insmod df
11.拷貝網卡模塊
modinfo e1000
cp /lib/modules/3.10.0-693.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000/e1000.ko.xz /mnt/lib/modules

12.sync;sync;poweroff
13.創建新虛擬機,然後到硬盤創建步驟時,將硬盤文件從舊虛擬機的目錄復制到新虛擬機的目錄下。然後選擇使用現有的硬盤,指定到該硬盤文件。最後開機。

1.清空/dev/sda的前446字節
2.清空/dev/sda的前10240字節,跳過512
3.刪除grub.conf
4.刪除/boot/grub
5.刪除/boot
6.刪除/etc/init/rcS.conf
7.刪除/etc/rc.d/rc.sysinit
8.刪除/etc/fstab

外加題:用戶空間、內核空間、Tcp/ip協議棧

第三十二天、

1.kernel: 驅動程序集成到內核或模塊化在內存調用

lsmod 列出已加載的所有模塊
modinfo 模塊名 顯示某模塊的詳細信息

加載模塊
modprobe 模塊名 :modprobe 只能跟模塊名,在編譯內核加載模塊時如果使用絕對路徑則不行,使用insmod
加載模塊名--使用模塊名的絕對路徑
insmod /mode..
卸載模塊
modprobe -r 模塊名

1.wget ftp://172.18.0.1/pub/Sources/sources/kernel/x.x.x.gz
2.tar -xvf x.x.x.xz
3.cp /boot/config... /root/x.x.x/.config 這樣可以使用本系統的內核配置文件來替換編譯內核時默認生成的config文件,能夠使本系統支持
4.make menuconfig
5.make -j cpu核心數量 此為使用指定分配的cpu核心數量進行編譯;使用lscpu 或 cat /proc/cpuinfo查看
註意:在編譯過程中出現的報錯的都不需擔心,根據提示缺少的就是需要安裝的包,可以使用rpm -qf qi 或者 yum list yum search ....
6.模塊基本都是在內存中加載到內核,集成到內核的驅動不大
7.編譯寫入/boot的時候一定要註意,/boot的可用空間情況,否則可能導致失敗;編譯安裝之後不要將新編譯的內核調整為第一個,而是應該保持默認選擇,手動選擇啟動,否則啟動失敗導致網卡模塊加載不了~跑機房; 在進行長時間不間斷的工作時,必須使用screen來進行保護進程操作
8.啟動之後 cat /var/log/boot.log針對性查看是否完全成功

selinux

1.添加或者修改port類型的時候,對對應服務的配置文件首先要分清客戶端(ssh_config)和服務端(如sshd_config)配置文件,然後將註釋的PORT去掉註釋,生效
2.思考思路重要: 1.服務端的配置的文件; 2.iptables防火墻策略; 3. selinux策略 tailf /var/log/xxxservice 根據日誌semanage ...復制查看,

lsmod 列出已加載的所有模塊
modinfo 模塊名 顯示某模塊的詳細信息

加載模塊
modprobe 模塊名
卸載模塊
modprobe -r 模塊名

1.wget ftp://172.18.0.1/pub/Sources/sources/kernel
2.tar -xvf x.x.x.xz
3.cp /boot/config... /root/x.x.x/.config
4.make menuconfig
4.make -j cpu核心處理器數量 :在分配好給服務器處理器的數量以及對應的核心處理器的數量後,全部指定使用會加快編譯處理
5.make modules_install
6.make install

6/ make clean 清理編譯後的二進制文件,保留源碼文件
7.reboot

重啟後可以查看啟動日誌
cat /var/log/boot.log

單獨編譯某個模塊
make fs/ntfs/ntfs.ko

作業:
1、破解root口令,並為grub設置保護功能
2、破壞本機grub stage1,而後在救援模式下修復之
3、刪除vmlinuz和initramfs文件後無法啟動,兩種方法恢復之
4、增加新硬盤,在其上制作能單獨運行kernel和bash的系統
5、在U盤上定制linux,使其可啟動系統,並具有網絡功能
6、刪除/etc/fstab和/boot目錄的所有文件,並恢復之
7、編譯安裝kernel,啟用支持ntfs文件系統功能

selinux
enforcing:強制模式
permissive: 警告模式
disabled:關閉模式

setenforce 0|1 警告|強制 使用臨時禁用切換方式可以初步判斷是否是selinux的問題,後續繼續進行操作
sestatus 查看當前的狀態
vim /etc/selinux/config
SELINUX=enforcing|permissive|disabled 決定下次開機時的selinux狀態
系統啟動在stage 2階段的時,可更改內核參數,最後加上selinux=0表示disabled selinux=1表示enforcing

系統默認的文件系統以及其下的子目錄和文件都是有默認的selinux安全上下文的期望值,可以通過restorecon -R 來通過期望值標簽的數據庫來進行恢復,而如果是新創建的文件系統或者目錄是沒有期望值標簽的,所以引入增加期望值的方式添加到數據庫中:

增加期望值 :此處 /app/website(/.)? 是利用正則表達式對website目錄下判斷是否含有其他的文件或者子目錄,如果有則對其一並進行添加selinux標簽
[root@centos7 website]# semanage fcontext -a -t httpd_sys_content_t ‘/app/website(/.
)?‘
restorecon -R /app/website/ :此處註意,是與chcon有相同之處,在對於目錄及其下的子目錄或者文件進行重設標簽期望值的時候必須使用-R遞歸!
修改期望值
[root@centos7 website]# semanage fcontext -m -t var_log_t ‘/app/website(/.*)?‘

刪除期望值

[root@centos7 website]# semanage fcontext -d ‘/app/website(/.*)?‘

增加端口號
semanage port -a -t http_port_t -p tcp 9527

生產環境為了安全起見,將一些高安全的服務端口都要進行更改,所以要使用semange port 對selinux期望策略數據庫中服務bind的port進行增加策略,在進行修改配置文件使其生效

刪除端口號
semanage port -d -t http_port_t -p tcp 9527

SELINUX boolean 對服務設置安全策略,對某項動作進行開關設置(on/off)
semanage boolean -l |grep serciexxx or semanage boolean -l |less 翻頁查看
setsebool [-P] ftp_anon_write=on 開啟匿名用戶通過ftp服務上傳功能 -P寫入並保存設置

*****示例:通過Http協議將某用戶的家目錄共享出去
~userhomedir :進入某用戶家目
1.首先對httpd服務進行配置,對http.conf文件 UserDir Disabled進行註釋,並取消 UserDir public_html #根據註釋說明應該在啟用後必須在共享的用戶家目錄下創建 public_html;
2.當服務配置完成之後,要考慮的是防火墻或者就是selinux安全策略 semange boolean -l |grep http,此時在考慮selinux之前先通過瀏覽器Http進行訪問 ip/~username/
結果顯示forbidden,此為訪問時通過使用httpd進程的用戶身份對此目錄沒有訪問權限(x),而執行某一個進程取訪問某個目錄或者文件的時候必須以用戶的身份進行,所以httpd服務進程的用戶通過ps查看是apache,而共享的用戶家目錄的權限對其他人來講師---,所以此時應該使用setfacl -m u:apache:x dirname 對臨時用戶開啟訪問控制列表,針對目錄最小權限是X即可

yum -y install setroubleshoot selinux排錯日誌管理
1.安裝完成後如果有SELINUX報錯警告,會在圖形化界面上方有棕×××標點擊查看詳細信息;
2.setroubleshoot將錯誤信息寫入/var/log/messages中,通過 tail -n 10 /var/log/messages |grep setroubleshoot可以快速查看,在命令行執行信息提示中 run後面的 sealert -l ...進行格式化顯示,易讀
3.在圖形化界面如果關閉了報警圖標不再顯示,可以執行 sealert 就可重新調取selinux報警圖標
4.信息來源 /var/log/audit/audit.log

SELINUX幫助文檔的安裝 : centos7.2 selinux-policy-devel ; centos7.3 selinux-policy-doc

  1. 執行mandb 因為安裝完幫助文檔包之後,數據庫是非實時性的,需要通過mandb 或者 makewhatis(centos6)進行數據庫更新寫入;文檔信息以及各種信息都要借助數據庫
    2.man -k _selinux
    3.man 8 httpd_selinux 針對具體的httpd服務的selinux策略進行查看幫助文檔! man 8 service_selinux

/etc/ssh/sshd_config
resuce救援模式默認是不開啟selinux,所以退出後重啟系統會重新打標簽; 等於 restorecon [R]

1.logger “...” : logger "content.." 可以用來測試日誌,手動生成 -->對應的進程是/usr/sbin/rsyslogd ,服務名稱是rsyslog
如果 cp /var/log/messages /root/ ,此時復制之後的root下的messages文件ls -Z後發現是繼承了root目錄的標簽, mv /root/messages /var/log/messages進行覆蓋,此時/var/log/messages文件的標簽還是root目錄的不會變化; logger "..." 測試日誌寫入功能發現並未開啟日誌寫入,所以:
(change context) chcon -R var_log_t /var/log/messages ,service rsyslog restart 或者 systemctl restart rsyslog (重啟日誌服務才能對配置以及日誌文件等重新讀取標簽,因為進程是挑文件標簽的即selinux的security context); chcon -R directory 針對目錄必須是-R

cp 會使得復制後的文件繼承所在當前目錄的標簽,而mv並不會使得文件標簽有所變化: 所以,在某些場景下,文件權限以及文件其他表面數據都沒有異常的情況下,用戶或者進程不能正常訪問文件和執行寫操作了,要考慮其中之一的selinux標簽策略問題

2.外加知識小結:關於用戶客戶端通過瀏覽器訪問Linux服務器上的站點:主要就是通過瀏覽器域名和端口通過linux服務器上apache這個website用戶及用戶組身份進行的一系列訪問(進程必須要以一個用戶的身份去進行文件的訪問等操作); 所以,對於權限的設定盡量不能chmod 777 user ,而是對在不同目錄下的html目錄進行標簽重設,然後重啟httpd服務,然後使用setfacl訪問控制列表對某些如apache用戶進行權限控制,從而達到安全的開放權限的訪問目的(當然selinux是作用在最後的一層的防護,前面服務配置文件、防火墻、權限等都可優先設計);
通常情況下訪問web的時候都是80,在實際環境中通過對端口的更改導致正常訪問的某些服務不能訪問或者鏈接,因為正常的建立socket是 (ip:port),端口的更改就會導致這種問題

第三十三天、 AWK 指定格式報表輸出 非常重要

1.awk 如果變量RS ORS同時指定了,ORS輸出記錄分隔符取代的是RS,原默認換行符不替換
2.awk BEGIN‘{print ARGV[ARGC-1]}‘ 1 2 3 ;如果想要將文件名作為參數輸出而不讀文件內容,使用ARGV[N]
3.awk 在使用正則匹配的時候必須使用雙引號將字符串引起 df |awk ‘$0 ~ "/dev/sd" {printf "DEVICENAME:%-15s USEDSPACE:%s\n",$1,$3}‘; !~表示左邊不包含匹配
4.linux中對於未聲明初始值的變量或數組在進行數學運算時,會自動識別為0
5.‘pattern{action statements...}‘ filename 當pattern為boolean值時,1為真,0為假(這裏一定要嚴格區分命令的退出狀態返回值 $?)省略{action}部分默認打印$0即全域
為假時不執行 awk ‘i=1;j=1{print i,j}‘ /etc/passwd --> i=1;相當於i=1{print $0};j=1{print i,j}
6.awk中對於字符以及字符串的使用必須使用雙引號,否則都視為變量,沒有賦值的變量如果要輸出則給0,在邏輯運算中沒有任何意義忽略

7、使用awk打印奇偶行:
打印奇數行: seq 10 |awk ‘i=!i‘
打印偶數行: seq 10 |awk ‘!(i=!i)‘
seq 10 |sed -n 1~2p
seq 10 |sed -n 2~2p

8.BEGIN是在未讀取文件內容前執行,而END則是讀取文件最後一行執行,NR在END中就可以用來統計行數
[root@magedu(CentOS7) 2018-03-30 ~]# awk -F":" -v sum=0 ‘BEGIN{print "USERNAME salary"}{sum+=$3;printf "%-20s %s\n",$1,$3}END{sum=sum/NR;printf "avgsalary=%s\n",sum}‘ /etc/passwd 最後顯示平均工資

[root@magedu(CentOS7) 2018-03-30 ~]# awk -F: ‘BEGIN{printf "USERNAME SALARY LEVEL\n-------------------------------\n"}{if($3>3000){printf "%-20s %-10s %s\n",$1,$3,"high"}else if($3>1000){printf "%-20s %-10s %s\n",$1,$3,"soso"}else{printf "%-20s %-10s %s\n",$1,$3,"low"}}‘ /etc/passwd

:調試小總結,必須註意指定輸入分隔符;printf要主動換行 ;else if(); 在awk的判斷語句中定義變量,在整個action部分並不會全部重置(分判斷情況);對於整數站位符最好使用%d; 在內置函數中比如要length(string)取長度,必須使用雙引號對字符串進行引用,否則就會被識別為變量(未賦值的變量為空或0) length("string");
:在action部分使用循環時,必須註意變量初始值重置問題 n=1; while(n<=NF){..;n++} ,如果不定義n=1,則在執行完第一條記錄後,後面的記錄的判斷條件n不會重置1,所以註意區分每條記錄的字段循環處理即內部處理,初始值不重置;記錄刷新重新讀取新的記錄則之前定義的變量初始值重置;

[root@magedu(CentOS7) 2018-03-30 ~]# awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i}{print sum}}‘
5050 -->註意:循環計算中,一個變量尤其是作為循環條件的變量不可能即作為計數器又作為求和等變量,必須另定義

** time awk ‘{..}‘ 使用time來進行處理用時計算,從而得出awk來計算的速度相對最快 ,所以,經常使用awk


2.awk 數組: 在使用循環如for循環的時候 for n in array ,則n表示array數組的下標
1.awk ‘/([[:digit:]]{1,3}.){3}.([[:digit:]]{1,3})/{print $0}‘ access_log

小總結:1.ip[$1] 這裏awk應該根據文件的內容的具體格式進行指定具體點分隔符;
ip[$1]取的是每條記錄的第一個域也就是Ip,因為變量或者數組在awk中只是隱式聲明但未賦值的情況下,在參數比較或者數學運算的時候是初始值默認0的,所以可以進行++等運算,讓數組key為已知條件內容Ip,值為對應的自增後的數量從而統計出Ip對應的訪問數量

       2. awk ‘!ip[$1]++‘ access_log  直接輸出一次統計,利用取反非0不執行

    [root@magedu(CentOS7) 2018-03-30 ~]# awk ‘BEGIN{printf "IP              IP_COUNT\n----------------------------\n"}/^[^:]/{ip[$1]++}END{for(n in ip){printf "%-18s-->%s\n",n,ip[n]}}‘ access_log 

        IP              IP_COUNT
        ----------------------------
        172.18.253.55     -->1788
        172.18.251.122    -->52
        172.18.251.150    -->34
        172.18.251.141    -->30
        172.18.251.160    -->157
        172.18.251.170    -->457
        172.18.251.107    -->14
        172.18.251.109    -->51
        172.18.251.145    -->50
        172.18.0.223      -->12
        172.18.253.21     -->74087
        172.18.251.147    -->354
        172.18.254.78     -->183
        172.18.251.157    -->330
        172.18.252.134    -->514
        172.18.251.149    -->158
        172.18.254.6      -->1643
        172.18.250.183    -->81
        172.18.251.21     -->81
        172.18.254.34     -->659

    for i in $(sipcalc ${ip_mask} | grep Usable|egrep -o "[0-9.]+" | eval echo `awk ‘{a[NR]=$0}END{split(a[1],b,".");split(a[2],c,".");for(i in b){if(b[i]!=c[i]){b[i]="{"b[i]".."c[i]"}"}};print b[1]"."b[2]"."b[3]"."b[4]}‘` | tr " " "\n")

第三十四天

cut
cat -n
bc $[]

awk -F: ‘{printf "username:%-20s salary:%-10.2f shell:%s\n",$1,$3,$7}‘ /etc/passwd

[root@centos7 ~]# df |grep /dev/sd |awk ‘{printf "DevName:%s Used:%s\n",$1,$5}‘
DevName:/dev/sda2 Used:19%
DevName:/dev/sda3 Used:1%
DevName:/dev/sda1 Used:55%

[root@centos7 ~]# df | awk ‘$0 ~ "/dev/sd" {printf "DevName:%-10s Used:%s\n",$1,$5}‘
DevName:/dev/sda2 Used:19%
DevName:/dev/sda3 Used:1%
DevName:/dev/sda1 Used:55%

[root@centos7 ~]# df |awk ‘$1~"^/dev/sd[[:lower:]][[:digit:]]\>" && $5>=10 {printf "Filesystem: %-15s Used: %s\n",$1,$5}‘
Filesystem: /dev/sda2 Used: 95%
Filesystem: /dev/sda1 Used: 48%

[root@centos7 ~]# df |awk ‘/\/dev\/sd[[:lower:]][[:digit:]]\>/{if($5>10){printf "DevName:%-10s Used:%s\n",$1,$5}}‘
DevName:/dev/sda2 Used:19%
DevName:/dev/sda1 Used:55%

awk -F : ‘{print "USER USERID“;print $1":"$3} END{print "end file"}‘ /etc/passwd

練習:將/etc/passwd第一列當作姓名,第三列當作工資,打印報表,要求顯示:
Name:zhangsan Salary:3300 Level:High
工資大於3000的,Level顯示High,大於1000,小於等於3000的顯示Soso,小於1000的顯示LOW。

[root@LiuHongsen7 ~]# awk -F: ‘{if($3>3000){Level="High"}else if($3>1000 && $3<=3000){Level="Soso"}else{Level="Low"};printf "Name:%-20s Salary:%-20d Level:%s\n",$1,$3,Level}‘ /etc/passwd

[root@centos7 ~]# cat /root/grub2.cfg |awk ‘/^[[:space:]]+linux16/{n=1;while(n<=NF){print $n,length($n);n++}}‘

練習:利用echo {1..10},打印如下結果
1 jishu
2 oushu
3 jishu
4 oushu
……
10 oushu

[root@nana ~]# echo {1..10} |awk ‘{i=1;while(i<=NF){if($i%2==0){print $i,"is oushu"} else{print $i, "is jishu"};i++}}‘
1 is jishu
2 is oushu
3 is jishu
4 is oushu
5 is jishu
6 is oushu
7 is jishu
8 is oushu
9 is jishu
10 is oushu

[root@nana ~]# awk ‘{i=1;sum=0;while(i<=NF){sum+=$i;i++};print sum}‘ f1.txt 顯示每行各自的總行
55
155
[root@nana ~]# awk ‘{i=1;while(i<=NF){sum+=$i;i++};print sum}‘ f1.txt 每行顯示一次總和
55
210
[root@nana ~]# awk ‘{i=1;while(i<=NF){sum+=$i;i++}}END{print sum}‘ f1.txt 只顯示總和
210

[root@centos7 ~]# awk ‘/[[:space:]]+linux16/{for(n=1;n<=NF;n++){print $n,length($n)}}‘ /root/grub2.cfg
linux16 7
/vmlinuz-3.10.0-693.el7.x86_64 30
root=UUID=be5fceff-51ad-43b7-82e4-84eabedb4e4f 46
ro 2
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-8a71aef45fd94de19b4ba1c81c836c34 50
root=UUID=be5fceff-51ad-43b7-82e4-84eabedb4e4f 46
ro 2
rhgb 4
quiet 5

計算1加到100和為多少 : awk 內部算法問題,所以如果涉及到大量運算或者性能處理上要求速度,使用awk能夠很大提高計算
使用time awk ‘{}‘ :time命令可以對命令的執行計算時間
[root@centos7 ~]# echo {1..100}|tr " " + |bc
5050
[root@centos7 ~]# for ((sum=0,i=1;i<=100;i++));do let sum+=i;done;echo $sum
5050
[root@centos7 ~]# awk BEGIN‘{for(i=1;i<=100;i++){sum+=i};print sum}‘
5050
[root@centos7 ~]# awk BEGIN‘{i=1;while (i<=100) {sum+=i;i++};print sum}‘
5050

[root@centos6 ~]# awk BEGIN‘{sum=0;for(i=1;i<=100;i++){if(i%2==0){continue};sum+=i};print sum}‘
2500
[root@centos6 ~]# awk BEGIN‘{sum=0;for(i=1;i<=100;i++){if(i%2==1){continue};sum+=i};print sum}‘
2550
[root@centos6 ~]# awk BEGIN‘{sum=0;for(i=1;i<=100;i++){if(i%2==0){break};sum+=i};print sum}‘
1

[root@centos6 ~]# seq 10 |awk ‘{if($1%2==0){next};print $1}‘
1
3
5
7
9
[root@centos6 ~]# seq 10 |awk ‘{if($1%2!=0){next};print $1}‘
2
4
6
8
10

[root@centos6 ~]# awk ‘BEGIN{weekday["mon"]="Monday";weekday["tue"]="Tuesday";weekday["wen"]="Wendsday";for (n in weekday){print weekday[n]}}‘
Wendsday
Monday
Tuesday

[root@centos6 ~]#awk -F: ‘{shell[$7]++}END{for(n in shell){print n,shell[n]}}‘ /etc/passwd

[root@centos6 ~]#awk ‘{ip[$1]++}END{for(n in ip){print n,ip[n] }}‘ access_log

[root@centos6 ~]#awk -F: ‘!shell[$0]++‘ /etc/passwd 去重

[root@nanyibo ~]# netstat -tan |awk ‘/^tcp/{state[$NF]++}END{for (n in state){print n,state[n]}}‘
LISTEN 10
ESTABLISHED 1

[root@nanyibo ~]# awk ‘BEGIN{srand();print int(rand()*100)}‘

[root@nanyibo ~]# echo "2018:3:30 17:38:30" |awk ‘sub(/:/,"-",$1)‘
2018-3:30 17:38:30
[root@nanyibo ~]# echo "2018:3:30 17:38:30" |awk ‘gsub(/:/,"-",$1)‘
2018-3-30 17:38:30

[root@nanyibo ~]# cat netstat.log |awk ‘/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}‘

[root@nanyibo ~]# cat awk.txt
function max(v1,v2){
v1>v2?var=v1:var=v2
return var
}
BEGIN{print max(a,b)}
[root@nanyibo ~]# awk -v a=30 -v b=20 -f awk.txt
30
[root@nanyibo ~]# awk -v a=10 -v b=20 -f awk.txt
20

***3.awk經典實例,一次處理多個文件,根據NR FNR的比較返回值進行文件內容格式化報表輸出處理:
說明:由NR=FNR為真時,判斷當前讀入的是第一個文件a,然後使用{a[$2]=$0;next}
循環將a文件的每行記錄都存入數組a,並使用$2第2個字段作為下標引用.
由NR=FNR為假時,判斷當前讀入了第二個文件b,然後跳過{a[$2]=$0;next},對第二個文件cdr的每一行都無條件執行{print a[$1]"|"$2},
此時變量$1為第二個文件的第一個字段,與讀入第一個文件時,采用第一個文件第二個字段$2為數組下標相同.因此可以在此使用a[$1]引用數組。
accout文件:張三|000001
李四|000002

    money文件:  000001|10
                 000001|20
                 000002|30
                 000002|15

   [root@magedu 2018-03-24 app]# awk -F"|" ‘NR==FNR{a[$2]=$0;next}{print a[$1],$2}‘ awk_test/{accout,money}
                            張三|000001 10
                            張三|000001 20
                            李四|000002 30
                            李四|000002 15
 *** pattern{action...}{action...}  :當action部分緊靠的前面的模式部分為真時則執行,使用Next可直接跳過當前行讀取下一行進行處理;而當pattern部分為假時,則跳過第一個緊靠的action部分而執行第二個action部分-->註意!!
 *** 區分next 和continue: next是跳過對當前行的處理或者其他處理(根據next的使用位置)而直接讀取下一行記錄處理;continue是直接跳過當前循環剩下部分進入到下一次循環 

作業:計算男生總成績,男生平均成績,女生總成績,女生平均成績
mage 100 male
dongyang 90 male
yunzhen 60 female
lilin 100 female

male 190 95
female 160 80

作業:
? 1、統計/etc/fstab文件中每個文件系統類型出現的次數
? 2、統計/etc/fstab文件中每個單詞出現的次數
? 3、提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中
的所有數字
? 4、解決DOS攻擊生產案例:根據web日誌或者或者網絡連接
數,監控當某個IP並發連接數或者短時內PV達到100,即調
用防火墻命令封掉對應的IP,監控頻率每隔5分鐘。防火墻命
令為:iptables -A INPUT -s IP -j REJECT

馬哥教育第三十一天至三十四天學習總結