標簽:Linux
系統(tǒng)運維, 經(jīng)驗雜筆華為光貓HS8145V交叉編譯靜態(tài)tcpdump
先森是個網(wǎng)速強迫癥,閑著沒事就喜歡研究光貓、路由器那一套,還希望在任何地方只要有網(wǎng)就能控制家里的設備。可惜先森的電信光貓是大內(nèi)網(wǎng),雙層NAT,沒有ipv4公網(wǎng)IP,結(jié)果偶然先森發(fā)現(xiàn)家里設備都可以直連ipv6了,而且分配到設備的ipv6地址還是公網(wǎng)的,先森就想著使用ipv6來突破網(wǎng)絡限制。結(jié)果,運營商為了保證安全,默認是限制了ipv6入訪的。由于家里寬帶不是先森辦理的,先森不太方便直接將光貓改為橋接的模式,所幸是先森拿到了光貓超管密碼,還可以通過shell的方式去操作iptables調(diào)整入訪策略。但光貓的iptables策略特別多,先森也得為安全考慮,不能直接全放通,所以得進行測試。結(jié)果問題來了,光貓的shell中沒有tcpdump的命令,沒法抓包,讓先森調(diào)試的心態(tài)爆炸,當時各種搜索都沒有找到光貓抓包的方法。由于ipv6的支持在先森身邊依舊不是那么普遍,像先森公司的商纖就沒有分配ipv6(不知道是不是公司IT把ipv6分配給關了),騰訊云CDN回源也不支持ipv6源站,所以當時先森一條條iptables策略調(diào)試的差不多之后,也就擱置了。但是沒法運行tcpdump抓包這個事一直讓先森如鯁在喉,然后最近突然知道了“交叉編譯”這么一個玩意兒,讓先森沉寂的心死灰復燃。交叉編譯:交叉編譯是在一個平臺上生成另一個平臺上的可執(zhí)行代碼。如在x86平臺上編譯ARM平臺上運行的可執(zhí)行代碼。先森在折騰的過程中遇到很多坑,在這里記錄一下。配置情況光貓:華為HS8145V,已經(jīng)開啟telnet;交叉編譯主機:CentOS 7.9 x86_64,其實應該用Ubuntu來交叉編譯更方便,但是先森對這系統(tǒng)不熟。交叉編譯器的尋找歷程確認平臺在網(wǎng)上搜交叉編譯tcpdump的教程,一開始根本沒注意到編譯器,然后直接上手編譯,這就跟平時正常編譯一樣,編譯出來的是gcc編譯的,根本不是交叉編譯的。網(wǎng)上教程說要確認目標機是arm-linux還是mips-linux什么的,先森看光貓通過telnet登錄的時候有什么BusyBox、Dopra Linux,搜了一圈也沒能明確搜出來華為光貓的系統(tǒng)屬于什么,只是搜到有說華為光貓使用的是海思芯片,屬于arm架構(gòu)的,最后是`uname -m`確認到華為這個是arm平臺。選擇arm-linux-gcc確認了光貓HS8145V是arm后,目標就很明確了,下載一下交叉編譯器,然后開整。但先森萬萬沒想到,arm-linux-gcc的下載鏈接那么難找,好不容易找到了,結(jié)果又發(fā)現(xiàn)arm-linux-gcc有很多版本,還要根據(jù)光貓arm的情況來選。arm-linux-gcc的不同版本那么光貓是什么情況呢,可以在命令行進行查看:WAP(Dopra Linux) # uname -aLinux EchoLife_WAP 3.10.53-HULK2 #1 SMP Fri Oct 20 01:08:58 CST 2017 armv7l GNU/Linux或者直接WAP(Dopra Linux) # uname -marmv7l實際在搜交叉編譯的教程時,要不就是單純的arm-linux-gcc,不然就是gcc-arm-linux-gnueabi和gcc-arm-linux-gnueabihf,所以就搜armv7l屬于哪種。百度了半天,好像都說armV7屬于armhf,想來armv7l應該也是,但實測不行,還得是armel。具體可以了解一下:arm-linux-gnueabi-gcc 和 arm-linux-gnueabihf-gcc:兩個交叉編譯器分別適用于 armel 和 armhf 兩個不同的架構(gòu),armel 和 armhf 這兩種架構(gòu)在對待浮點運算采取了不同的策略(有 fpu 的 arm 才能支持這兩種浮點運算策略)。其實這兩個交叉編譯器只不過是 gcc 的選項 -mfloat-abi 的默認值不同。gcc 的選項 -mfloat-abi 有三種值 soft、softfp、hard(其中后兩者都要求arm 里有 fpu 浮點運算單元,soft 與后兩者是兼容的,但 softfp 和 hard 兩種模式互不兼容):soft: 不用fpu進行浮點計算,即使有fpu浮點運算單元也不用,而是使用軟件模式。softfp: armel架構(gòu)(對應的編譯器為 arm-linux-gnueabi-gcc )采用的默認值,用fpu計算,但是傳參數(shù)用普通寄存器傳,這樣中斷的時候,只需要保存普通寄存器,中斷負荷小,但是參數(shù)需要轉(zhuǎn)換成浮點的再計算。hard: armhf架構(gòu)(對應的編譯器 arm-linux-gnueabihf-gcc )采用的默認值,用fpu計算,傳參數(shù)也用fpu中的浮點寄存器傳,省去了轉(zhuǎn)換,性能最好,但是中斷負荷高。下載arm-linux-gcc由于先森arm-linux-gcc的下載地址時比較痛苦,有點難找,所以顯示把各種版本的鏈接在這里列一下。下載單純的arm-linux-gcc,版本較老,4.4.3貌似是2010年發(fā)布的了資源地址:http://www.friendlyelec.com.cn/download.asp在頁面中可以找到下載地址:http://112.124.9.243/arm9net/mini2440/linux/arm-linux-gcc-4.4.3-20100728.tar.gz下載arm-linux-gnueabi或arm-linux-gnueabihf,資源下載列表頁是先選gcc版本,再選編譯器架構(gòu),最后還要選架構(gòu)運行平臺,這里先森選的是最新版本latest-7中的arm-linux-gnueabi的64位系統(tǒng)版本。由于這個頁面加載較慢或者未free無法打開,所以先森把兩個版本的下載地址都貼出來:資源列表頁:http://releases.linaro.org/components/toolchain/binaries/armel架構(gòu):http://124.156.146.205/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xzarmhf架構(gòu):http://124.156.146.205/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi.tar.xz配置arm-linux-gcc# 下載后解壓tar -xJvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi.tar.xz# 可選,先森是將其移動重命名了一下mv gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi /usr/local/arm# 可選,但建議操作cd /usr/local/arm/binln -s arm-linux-gnueabi-gcc arm-linux-gcc建議增加環(huán)境變量,不然編譯的時候./configure的參數(shù)需要加上'CC=/usr/local/arm/bin'echo 'export PATH=$PATH:/usr/local/arm/bin' >> /etc/profilesource /etc/profile添加環(huán)境變量后,需要執(zhí)行`arm-linux-gcc -v`測試一下arm-linux-gcc是否存在問題,可能會遇到下面的問題:bin/.arm-none-linux-gnueabi-gcc: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory# 解決方法:yum install -y ld-linux.so.2到這里終于把arm-linux-gcc部分弄完了,下面進入編譯環(huán)節(jié)。交叉編譯libpcap和tcpdump由于tcpdump需要依賴libpcap,所以需要下載這個包,分別編譯,先森下載的最新版本:https://www.tcpdump.org/release/tcpdump-4.99.1.tar.gzhttps://www.tcpdump.org/release/libpcap-1.10.1.tar.gz交叉編譯libpcap前面準備工作做好了,libpcap還是很好編譯的。下載解壓后,進入libpcap目錄中:./configure --prefix=/tmp/armroot --host=arm-linux --target=arm-linux --with-pcap=linuxmakemake install# –prefix指定目標文件生成路徑(makefile里面的target存放路徑);# –host、–target都寫成目標平臺即可,例如:arm-liux或mips-linux,光貓是arm的,所以寫arm-linux# --with-pcap將告訴編譯器我們正在編譯哪種數(shù)據(jù)包捕獲類型# 如果前面沒有加arm-linux-gcc的環(huán)境變量,那么需要加上CC='/usr/local/arm/bin'編譯鏈路徑編譯時遇到的問題:# 問題1:configure: error: Neither flex nor lex was found.# 解決:yum install -y flex bison# 問題2:/usr/local/arm/bin/../libexec/gcc/arm-none-linux-gnueabi/4.4.3/cc1: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory# 解決:貌似和系統(tǒng)是64位,gcc是32位有關,安裝32位的庫即可yum install -y libstdc++.i686# 問題3:/usr/local/arm/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.3/../../../../arm-none-linux-gnueabi/bin/as: error while loading shared libraries: libz.so.1: cannot open shared object file: No such file or directory# 解決:yum -y install zlib.i686交叉編譯tcpdump實際測試,tcpdump的交叉編譯,必須是編譯靜態(tài)鏈接,編譯器默認是動態(tài)鏈接庫。由于光貓的根路徑是只讀的,而lib庫就在系統(tǒng)路徑中,無法在光貓?zhí)砑哟_實的動態(tài)鏈接庫文件,所以只能選擇靜態(tài)交叉編譯這條路了。解壓tcpdump包后,進入目錄進行操作:# 指定靜態(tài)交叉編譯export CFLAGS=-staticexport CPPFLAGS=-staticexport LDFLAGS=-staticexport ac_cv_linux_vers=3./configure --prefix=/tmp/armroot --host=arm-linux --target=arm-linuxmakemake install# 編譯好的文件就是當前目錄下的tcpdump文件,也可以去--prefix執(zhí)行的目錄的bin或sbin目錄找到tcpdump編譯tcpdump時遇到的問題:# 問題1:configure: error: cannot determine linux version when cross-compiling# 解決辦法:我們需要找出我們的 Ubuntu(或 Linux)操作系統(tǒng)內(nèi)核正在運行的主要版本。執(zhí)行 uname -a 命令。# 注意:您的輸出可能會有所不同,但請查找類似于版本號的內(nèi)容。下面,先森的主機是 3.10.0-1160.45.1.el7.x86_64,我們抓住第一個“3”。uname -aLinux VM-0-4-centos 3.10.0-1160.45.1.el7.x86_64 #1 SMP Wed Oct 13 17:20:51 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux# 然后將ac_cv_linux_vers 變量設置為上一個命令中發(fā)布的內(nèi)核版本的主要編號,再嘗試編譯export ac_cv_linux_vers=3# 問題2:/mnt/jffs2/tcpdump: can't load library 'libc.so.6'# 解決:缺的動態(tài)鏈接庫又沒法塞進光貓的系統(tǒng),所以需要靜態(tài)交叉編譯# 問題3:靜態(tài)編譯會遇到此類警告tcpdump.c:(.text+0x5a6): warning: Using 'initgroups' in statically linked applications requires at runtime the shared libraries from the glibc version used for linkin# 解決:正常現(xiàn)象,只是警告,不影響使用建議操作剝離符號信息,使二進制文件更小,這些符號僅在調(diào)試應用程序時有用,而光貓的存儲容量比較小。[root@VM-0-4-centos bin]# ll -htotal 14M-rwxr-xr-x 1 root root 1.9K Apr 2 16:32 pcap-config-rwxr-xr-x 1 root root 6.9M Apr 2 16:33 tcpdump-rwxr-xr-x 1 root root 6.9M Apr 2 16:33 tcpdump.4.99.1[root@VM-0-4-centos bin]# arm-linux-gnueabi-strip tcpdump[root@VM-0-4-centos bin]# ll -htotal 8.4M-rwxr-xr-x 1 root root 1.9K Apr 2 16:32 pcap-config-rwxr-xr-x 1 root root 1.5M Apr 2 16:34 tcpdump-rwxr-xr-x 1 root root 6.9M Apr 2 16:33 tcpdump.4.99.1拿到光貓上去運行折騰了這么多,最終能在光貓上運行才是第一目標。先森是直接把tcpdump放到服務器的web目錄中,然后光貓直接wget下載到光貓中的。先森在測試交叉編譯的運行中,遇到了很多錯誤,總結(jié)下來是以下4種:# 第一種報錯WAP(Dopra Linux) # ./tcpdump.Ullegal Illegal instruction# 第二種報錯WAP(Dopra Linux) # ./tcpdump.libc /mnt/jffs2/tcpdump.libc: can't load library 'libc.so.6'# 第三種報錯WAP(Dopra Linux) # ./tcpdump.0\:08 /mnt/jffs2/tcpdump.0:08: can't resolve symbol '__libc_start_main'# 第四種報錯WAP(Dopra Linux) # ./android-tcpdump android-tcpdump: eth0: You don't have permission to capture on that device(socket: Operation not permitted)事實上,除了第四種,前三種都是編譯有問題的版本,第四種只是提醒沒有權(quán)限執(zhí)行。沒有權(quán)限的情況,經(jīng)過一番搜索,先森找到了再次提權(quán)的方法(本來以為shell提權(quán)已經(jīng)是終點了),二次提權(quán)只需要su切到root,密碼:admin,可以通過whoami查看當前角色。二次提權(quán)后執(zhí)行成功寫在最后本來先森是想在文章最后把自己編譯好的文件分享出來的,結(jié)果在完善本文的時候搜到了一篇Android官方寫的tcpdump靜態(tài)交叉編譯的文檔,其中有詳細的靜態(tài)編譯步驟,也有官方編譯好的文件下載地址。先森試了一下,直接下載Android官方編譯的tcpdump也是能夠在光貓運行的,如果先森一開始就搜到了這邊文檔或資源。。。。文檔地址:https://www.androidtcpdump.com/android-tcpdump/compile直接下載:https://www.androidtcpdump.com/android-tcpdump/downloads
系統(tǒng)運維, 經(jīng)驗雜筆寶塔php如何安裝ldap擴展
今天打算在服務器上部署一個zabbix,做一些日常監(jiān)控,結(jié)果在配置網(wǎng)頁的時候,遇到了一點問題。zabbix安裝缺少ldap擴展既然缺少,那就安裝咯(當然,ldap擴展不是必須的,也可以忽略它繼續(xù)下一步)。安裝ldap擴展在網(wǎng)上看到的教程都是先編譯php,再安裝ldap擴展。可是先森這邊已經(jīng)使用寶塔安裝好了php,所以看他們的教程看的暈暈乎乎的,不過所幸還是折騰好了。第一步,下載php源碼寶塔的php擴展文件夾里是沒有l(wèi)dap的,所以我們需要去下載一個php完整的源碼包,將里面的ldap盤出來。下載源碼包的時候,需要與你寶塔已經(jīng)安裝的大版本匹配。先森安裝的是7.2的php,所以要去官網(wǎng)下載7.2版本的源碼,小版本就不用管了,先森下載的是7.2.25版本。在哪里下載?如果是7.2版本及更新的版本,可以直接在https://www.php.net/downloads.php如果是7.2版本以前的老版本,那就在舊檔案里面下載吧:https://www.php.net/releases/電腦下載可能會比較慢,畢竟源站在國外,一般來說用服務器下載會快一些。第二步,編譯ldap下載完畢php源碼包之后,解壓而入之,擴展文件夾是'ext',再入之,可見'ldap'。cd ./php-7.2.25/ext/ldap/進入ldap源文件目錄然后就可以開始編譯了。/www/server/php/72/bin/phpize #準備擴展庫的編譯環(huán)境./configure --with-php-config=/www/server/php/72/bin/php-config #編譯配置make && make install #編譯安裝ls /www/server/php/72/lib/php/extensions/no-debug-non-zts-20170718/ # 查看編譯好的ldap.so文件編譯與查看成果第三步,修改配置文件下面需要把ldap加到php.ini里面,添加的方式有兩種。php --ini #查看php.ini的位置:Configuration File (php.ini) Path: /www/server/php/72/etcLoaded Configuration File: /www/server/php/72/etc/php.ini第一種,取消php.ini原本的注釋將';extension=ldap'前面的引號刪除后重啟php-fpm即可。刪除注釋第二種,在末尾新增配置[ldap]extension = ldap.so新增配置第四步,重啟php添加配置后重啟php-fpm即可,可以命令行重啟,也可以在寶塔界面。service php-fpm-72 restart #重啟php重啟后再在zabbix界面查看就可以發(fā)現(xiàn)所有檢查都通過了。檢測通過
系統(tǒng)運維, 經(jīng)驗雜筆CentOS搭建lsyncd實時同步——取代rsync+inotify
昨天先森發(fā)布了“CentOS下inotify+rsync實現(xiàn)文件實時同步”,inotify+rsync實時同步的方案是用shell在后臺常駐來實現(xiàn)實時同步,沒有守護進程,感覺不是很靠譜,如果腳本突然掛了,實時同步豈不是GG了?所以先森在實現(xiàn)了inotify+rsync后還是再找其他的解決方案。其實在找到lsyncd之前,先森先找到了sersync這個工具,但是好像這個工具很久沒有更新了,所以雖然也有較多好評,但是先森目前還是先研究lsyncd了。當然,無論是sersync還是lsyncd,其實都是對inotify這個內(nèi)核中的文件事件監(jiān)控系統(tǒng)進行了封裝,類似inotify-tools,給我們提供的是封裝好了的inotify+rsync工具。sersync是用C寫的,lsyncd是使用lua語言封裝的。搭建lsyncd實時同步lsyncdlsyncd項目也托管在GitHub上面,具體地址是https://github.com/axkibe/lsyncd,一會兒若是要編譯安裝也需要去這個地方。上文也說過,lsyncd是使用lua語言封裝的,所以初識lsyncd的配置文件時,還是有點不習慣,但是用久應該就還好了。lsyncd不僅僅是實現(xiàn)兩臺服務器的同步的,它還能夠在一臺服務器內(nèi)對兩個文件夾進行同步,這里可以是cp,也可以是rsync。兩臺或多臺服務器間可以是rsync,也可以是rsyncssh。本文主要講的是兩臺服務器間的rsync。lsyncd可以配置inotify檢測到文件變動后多少秒才執(zhí)行同步,也就是時間延遲。也可以配置文件變動個數(shù)達到多少個后立即執(zhí)行同步,無論有沒有到達前面的時間延遲的要求,這就是累計觸發(fā)事件次數(shù)。這兩個配置可以減少rsync的同步,避免海量文件同步時rsync的頻繁發(fā)送文件對比列表。lsyncd安裝lsyncd的安裝方式有兩種,yum安裝和編譯安裝。yum安裝:yum安裝也有兩種方式,一個是阿里云的鏡像源,一個是fedoraproject的鏡像源。阿里云:#CentOS 7wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo#CentOS 6wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo#yum 安裝yum install lsyncd -yfedoraproject:#只找到CentOS 6的rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpmyum install lsyncd -y編譯安裝:1、首先還是去上文提到的GitHub上下載項目,通過下面的下載就是最新的了:wget https://github.com/axkibe/lsyncd/archive/master.zip2、下載了軟件包,先別急著安裝,上文提到了幾次,lsyncd是用lua語言封裝的,所以還需要安裝lua環(huán)境。另外lsyncd不是使用的make,而是cmake,所以也需要安裝cmake。yum install -y lua lua-devel asciidoc cmake3、下載了軟件包,裝好了環(huán)境依賴,下面就是編譯安裝:unzip lsyncd-master.zipcd lsyncd-mastercmake -DCMAKE_INSTALL_PREFIX=/usr/local/lsyncdmake && make install安裝好了的lsyncd在/usr/local/lsyncd下。配置文件、日志文件夾等需要我們自己定義與創(chuàng)建。4、配置文件。先森的配置文件是用于兩臺服務器間實時同步的,使用的是rsync模式。lsyncd的配置文件其實有點類似nginx,如nginx的server可以多定義互不沖突一樣,lsyncd也可以多個定義。settings { logfile ="/usr/local/lsyncd/logs/lsyncd.log", statusFile ="/usr/local/lsyncd/logs/lsyncd.status", inotifyMode = "CloseWrite or Modify", maxProcesses = 15, }sync { default.rsync, source = "/web/data/ftp", target = "user@172.17.8.16::datahome", delete="running", exclude = { ".*", ".tmp","*.swp","*.swx" }, delay = 0, rsync = { binary = "/usr/bin/rsync", archive = true, compress = true, verbose = true, password_file = "/etc/rsyncd/rsync.passwd", } }注釋版:settings { --定義日志文件 logfile ="/usr/local/lsyncd/logs/lsyncd.log", --定義狀態(tài)文件 statusFile ="/usr/local/lsyncd/logs/lsyncd.status", --指定inotify監(jiān)控的事件,默認是CloseWrite,還可以是Modify或CloseWrite or Modify --這個就是使用的inotify能監(jiān)控的事件 inotifyMode = "CloseWrite or Modify", --同步進程的最大個數(shù)。假如同時有20個文件需要同步,而maxProcesses = 8,則最大能看到有8個rysnc進程 maxProcesses = 15, --(這個配置先森沒有使用)累計到多少所監(jiān)控的事件激活一次同步,即使后面的delay延遲時間還未到。 --maxDelays=10, }sync { --使用rsync通過daemon方式連接遠程rsyncd進程; default.rsync, --同步的源目錄,使用絕對路徑。 source = "/web/data/ftp", --定義目的地址,對應不同的模式有不同的寫法。這里是遠程rsync,使用“用戶名@ip::模塊名”寫法。 target = "user@172.17.8.16::datahome", --是否同步刪除,除了running選項,還有true、false和startup,這個配置先森不是很明白,大概是true是完全同步刪除,false是不允許刪除,startup和running要難理解一些\ --先森的理解是,startup是僅在啟動時將源目錄和目的目錄來一次完全同步,lsyncd運行時的源目錄的刪除文件在目的目錄中不做刪除操作\ --running是啟動時不對源、目的目錄進行完全同步,lsyncd運行時源目錄刪除的文件,目的目錄也會被刪除。 delete="running", --排除的文件,這里排除了一些隱藏文件,和文件打開是時的臨時文件 exclude = { ".*", ".tmp","*.swp","*.swx" }, -- 累計事件,等待rsync同步延時時間,默認15秒。先森配置的是0,也就是實時同步。 delay = 0, rsync = { --本地rsync命令路徑 binary = "/usr/bin/rsync", archive = true, compress = true, verbose = true, --遠程rsyncd的密碼 password_file = "/etc/rsyncd/rsync.passwd", } }5、啟動lsyncd/usr/local/lsyncd/bin/lsyncd -log Exec /usr/local/lsyncd/lsyncd.conf也可以自己創(chuàng)建一個啟動腳本,腳本內(nèi)容如下,是先森從yum安裝的lsyncd拷貝的,一樣的可以使用。只是用之前,需要對lsyncd守護命令與配置文件先做個軟連接,免得需要修改啟動腳本:ln -s /usr/local/lsyncd/bin/lsyncd /usr/bin/lsyncdln -s /usr/local/lsyncd/lsyncd.conf /etc/lsyncd.conf啟動腳本:#!/bin/bash## chkconfig: - 85 15# description: Lightweight inotify based sync daemon## processname: lsyncd# config: /etc/lsyncd.conf# config: /etc/sysconfig/lsyncd# pidfile: /var/run/lsyncd.pid# Source function library. /etc/init.d/functions# Source networking configuration.. /etc/sysconfig/network# Check that networking is up.[ "$NETWORKING" = "no" ] && exit 0LSYNCD_OPTIONS="-pidfile /var/run/lsyncd.pid /etc/lsyncd.conf"if [ -e /etc/sysconfig/lsyncd ]; then . /etc/sysconfig/lsyncdfiRETVAL=0prog="lsyncd"thelock=/var/lock/subsys/lsyncdstart() { [ -f /etc/lsyncd.conf ] || exit 6 echo -n $"Starting $prog: " if [ $UID -ne 0 ]; then RETVAL=1 failure else daemon ${LSYNCD_USER:+--user ${LSYNCD_USER}} /usr/bin/lsyncd $LSYNCD_OPTIONS RETVAL=$? [ $RETVAL -eq 0 ] && touch $thelock fi; echo return $RETVAL}stop() { echo -n $"Stopping $prog: " if [ $UID -ne 0 ]; then RETVAL=1 failure else killproc lsyncd RETVAL=$? [ $RETVAL -eq 0 ] && rm -f $thelock fi; echo return $RETVAL}reload(){ echo -n $"Reloading $prog: " killproc lsyncd -HUP RETVAL=$? echo return $RETVAL}restart(){ stop start}condrestart(){ [ -e $thelock ] && restart return 0}case "$1" in start) start ;; stop) stop ;; restart) restart ;; reload) reload ;; condrestart) condrestart ;; status) status lsyncd RETVAL=$? ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}" RETVAL=1esacexit $RETVAL優(yōu)化因為lsyncd其實也是用到了inotify,所以和inotify+rsync方案一樣,我們還是需要對服務器的inotify內(nèi)核配置進行優(yōu)化。inotify檢查磁盤變動是有隊列等值的配置的,inotify默認內(nèi)核參數(shù)值太小,會導致實際檢測的時候報錯。查看系統(tǒng)默認參數(shù)值sysctl -a | grep max_queued_eventssysctl -a | grep max_user_watchessysctl -a | grep max_user_instances臨時修改sysctl -w fs.inotify.max_queued_events="99999999"sysctl -w fs.inotify.max_user_watches="99999999"sysctl -w fs.inotify.max_user_instances="65535"固定修改:vim /etc/sysctl.conf #添加以下代碼fs.inotify.max_queued_events=99999999fs.inotify.max_user_watches=99999999fs.inotify.max_user_instances=65535其他官方配置文件wiki:https://axkibe.github.io/lsyncd/manual/config/file/
腳本編程, 系統(tǒng)運維, 經(jīng)驗雜筆CentOS下inotify+rsync實現(xiàn)文件實時同步
rsync僅同步差異文件,所以傳輸效率較高,所以先森在項目中負載的資源服務器做了rsync同步,確保通過負載IP都能訪問到相同的文件,使用crontab計劃任務每1分鐘執(zhí)行一次同步。計劃任務最小時間刻度為1分鐘(雖然可以用數(shù)學方法再調(diào)小,但是運行密度大了對服務器會造成負荷),也就是上傳一張圖片,最長可能要等1分鐘后才能在其它服務器上訪問,如果同步目錄下的文件基數(shù)是百萬級的,那么時間可能更久。這種方案先森曾發(fā)過:CentOS下rsync服務器安裝與配置-數(shù)據(jù)同步|文件增量備份inotify+rsync實時同步rsync的不足rsync具有安全性高、備份迅速、支持增量備份等優(yōu)點,通過rsync可以解決實時性不高的數(shù)據(jù)備份需求,例如定期數(shù)據(jù)庫備份。但隨著業(yè)務規(guī)模的擴大,業(yè)務需求的增加,rsync的缺點也暴露出來了:1、當文件數(shù)量大到百萬級別,rsync僅差異掃描就是一項非常耗時的工作;2、rsync自身不能實時的檢測并同步數(shù)據(jù),它總是被動的通過各種方式去觸發(fā)同步。inotify與inotify-tools注:inotify是一個 Linux 內(nèi)核特性,inotify-tools是為linux下inotify文件監(jiān)控工具提供的一套C的開發(fā)接口庫函數(shù)。inotify:inotify是一種強大的、細粒度的、異步的文件系統(tǒng)事件監(jiān)控機制,Linux內(nèi)核從2.6.13開始引入,允許監(jiān)控程序打開一個獨立文件描述符,并針對事件集監(jiān)控一個或者多個文件,例如打開、關閉、移動/重命名、刪除、創(chuàng)建或者改變屬性。CentOS 6是已經(jīng)支持的了,判斷服務器是否支持inotify,只需要執(zhí)行下面命令,查看是否有結(jié)果即可。ll /proc/sys/fs/inotifyinotify-tools:inotify-tools是為linux下inotify文件監(jiān)控工具提供的一套C的開發(fā)接口庫函數(shù),同時還提供了一系列的命令行工具,這些工具可以用來監(jiān)控文件系統(tǒng)的事件。inotify-tools是用c編寫的,除了要求內(nèi)核支持inotify外,不依賴于其他。inotify-tools提供兩種工具,一是inotifywait,它是用來監(jiān)控文件或目錄的變化,二是inotifywatch,它是用來統(tǒng)計文件系統(tǒng)訪問的次數(shù)。我們主要用到的是inotifywait工具。inotify-tools安裝inotify-tools先森找到了兩種安裝方式,rpm安裝和編譯安裝,先森用的是編譯安裝。rpm安裝wget http://dl.fedoraproject.org/pub/epel/6/x86_64/Packages/i/inotify-tools-3.14-1.el6.x86_64.rpmrpm -vhi inotify-tools-3.14-1.el6.x86_64.rpm編譯安裝編譯前請確保服務器已安裝編譯組件:yum install -y make gcc gcc-c++這個項目是發(fā)布在github上的,下載也是在github上下載。但是先森在項目首頁下載下來的無法編譯安裝,所以安裝的還是3.1.4版本的。github項目地址:https://github.com/rvoicilas/inotify-tools/編譯安裝:wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gztar zxvf inotify-tools-3.14.tar.gzcd inotify-tools-3.14./configure #或./configure --prefix=/usr/local/inotifymakemake install安裝后命令在/usr/local/bin/目錄下。查看效果:/usr/local/bin/inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib /data/不停止上面的命令,新建終端連接然后進入/data/文件夾進行各類操作,可以看下上面輸出的結(jié)果。rsync組合inotify-tools完成實時同步inotify的作用,是讓我們知道監(jiān)控的文件夾中有變動,我們可以根據(jù)inotify輸出內(nèi)容,去觸發(fā)rsync同步。提示:以往使用crontab觸發(fā)rsync時,我們是將rsync服務端搭建在主服務器,其他服務器去主服務器同步文件。而inotify+rsync的方式,是將rsync服務端搭建在從服務器,主服務器推送文件到從服務器,所以從服務器上的rsync配置中“read only”要配置為no,也就是“read only = no”。inotify-tools只是個工具,并不是軟件,所以要與rsync配合就需要我們自己寫shell腳本,并讓腳本一直運行在后臺。先森通過實際測試,整理出了兩個腳本,也就是兩種方案。方案1:#!/bin/bashsource /etc/profilesrc=/data/ # 需要同步的源路徑des=datahome # 目標服務器上 rsync 模塊名rsync_passwd_file=/etc/rsyncd/rsync.passwd # rsync驗證的密碼文件ipaddr=(10.0.0.1) # 目標服務器,多個目標服務器以空格分開user=user # rsync --daemon定義的驗證用戶名logs=/var/log/inotify_rsync.logs # 日志inotify_rsync(){cd ${src} # 此方法中,由于rsync同步的特性,這里必須要先cd到源目錄,inotify再監(jiān)聽 ./ 才能rsync同步后目錄結(jié)構(gòu)一致,有興趣的同學可以進行各種嘗試觀看其效果/usr/local/bin/inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib,close_write,move --exclude=".*.swp" ./ | while read file # 把監(jiān)控到有發(fā)生更改的"文件路徑列表"循環(huán)do INO_EVENT=$(echo $file | awk '{print $1}') # 把inotify輸出切割 把事件類型部分賦值給INO_EVENT INO_FILE=$(echo $file | awk '{print $2}') # 把inotify輸出切割 把文件路徑部分賦值給INO_FILE echo "-------------------------------$(date)------------------------------------" echo $file #增加、修改、寫入完成、移動進事件 #增、改放在同一個判斷,因為他們都肯定是針對文件的操作,即使是新建目錄,要同步的也只是一個空目錄,不會影響速度。 if [[ $INO_EVENT =~ 'CREATE' ]] || [[ $INO_EVENT =~ 'MODIFY' ]] || [[ $INO_EVENT =~ 'CLOSE_WRITE' ]] || [[ $INO_EVENT =~ 'MOVED_TO' ]] # 判斷事件類型 then echo 'CREATE or MODIFY or CLOSE_WRITE or MOVED_TO' for ip in ${ipaddr[@]} do rsync -avzcR --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx" $(dirname ${INO_FILE}) ${user}@${ip}::${des} >> $logs # INO_FILE變量代表路徑哦 -c校驗文件內(nèi)容 done #仔細看 上面的rsync同步命令 源是用了$(dirname ${INO_FILE})變量 即每次只針對性的同步發(fā)生改變的文件的目錄(只同步目標文件的方法在生產(chǎn)環(huán)境的某些極端環(huán)境下會漏文件 現(xiàn)在可以在不漏文件下也有不錯的速度 做到平衡) 然后用-R參數(shù)把源的目錄結(jié)構(gòu)遞歸到目標后面 保證目錄結(jié)構(gòu)一致性 fi #刪除、移動出事件 if [[ $INO_EVENT =~ 'DELETE' ]] || [[ $INO_EVENT =~ 'MOVED_FROM' ]] then echo 'DELETE or MOVED_FROM' echo 'CREATE or MODIFY or CLOSE_WRITE or MOVED_TO' for ip in ${ipaddr[@]} do rsync -avzR --delete --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx" $(dirname ${INO_FILE}) ${user}@${ip}::${des} >> $logs done #看rsync命令 如果直接同步已刪除的路徑${INO_FILE}會報no such or directory錯誤 所以這里同步的源是被刪文件或目錄的上一級路徑,并加上--delete來刪除目標上有而源中沒有的文件,這里不能做到指定文件刪除,如果刪除的路徑越靠近根,則同步的目錄月多,同步刪除的操作就越花時間。這里有更好方法的同學,歡迎交流。 fi #修改屬性事件 指 touch chgrp chmod chown等操作 if [[ $INO_EVENT =~ 'ATTRIB' ]] then echo 'ATTRIB' if [ ! -d "$INO_FILE" ] # 如果修改屬性的是目錄 則不同步,因為同步目錄會發(fā)生遞歸掃描,等此目錄下的文件發(fā)生同步時,rsync會順帶更新此目錄。 then for ip in ${ipaddr[@]} do rsync -avzcR --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx" $(dirname ${INO_FILE}) ${user}@${ip}::${des} >> $logs done fi fidoneinotify_rsync >> $logs 2>&1}inotify_rsync >> $logs 2>&1將上面內(nèi)容保存為inotify_rsync_A.sh,執(zhí)行:inotify_rsync_A.sh &或使用screen后臺啟動。另外,為避免意外遺漏文件,最好在定時任務中每隔兩個小時執(zhí)行一次全目錄同步。這個方案的優(yōu)點:利用inotify讓rsync每次僅同步有更改的文件,減少遞歸操作。缺點:經(jīng)過先森實際運用發(fā)現(xiàn),inotify的特性,每次創(chuàng)建文件會產(chǎn)生多條輸出,而這個腳本inotify的每條輸出都會觸發(fā)一次rsync,這樣會對服務器資源產(chǎn)生浪費。方案2:為了解決方案1的問題,先森找到了另一個腳本,對方案1的腳本進行了修改:#!/bin/bashsource /etc/profilesrc=/data/ # 需要同步的源路徑des=datahome # 目標服務器上 rsync 模塊名rsync_passwd_file=/etc/rsyncd/rsync.passwd # rsync驗證的密碼文件ipaddr=(10.0.0.1) # 目標服務器,多個目標服務器以空格分開user=user # rsync --daemon定義的驗證用戶名inlogs=/var/log/inotifywait.logslogs=/var/log/inotify_rsync.logserrlog=/var/log/inotify_rsync.err.logscd ${src} # 此方法中,由于rsync同步的特性,這里必須要先cd到源目錄,inotify再監(jiān)聽 ./ 才能rsync同步后目錄結(jié)構(gòu)一致,有興趣的同學可以進行各種嘗試觀看其效果/usr/local/bin/inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib,close_write,move --exclude=".*.swp" ./ >> $inlogs &while true;do if [ -s ${inlogs} ];then grep -i -E "delete|moved_from" ${inlogs} >> /var/log/inotify_away.log for ip in ${ipaddr[@]} do rsync -avzcR --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx" ${src} ${user}@${ip}::${des} >> $logs RETVAL=$? done #同步失敗后的輸出日志 if [ $RETVAL -ne 0 ];then echo "${src} sync to ${ipaddr} failed at `date +"%F %T"`,please check it by manual" >> $errlog fi cat /dev/null > $inlogs for ip in ${ipaddr[@]} do rsync -avzcR --password-file=${rsync_passwd_file} --exclude="*.swp" --exclude="*.swx" ${src} ${user}@${ip}::${des} >> $logs done else sleep 1 fidone這個腳本是將inotify的檢測內(nèi)容輸出到文件/var/log/inotifywait.logs,腳本判斷這個文件是否為空,非空則表明有變動,那么就來一次完整的同步。如果文件為空則睡眠1秒。將上面內(nèi)容保存為inotify_rsync_B.sh,執(zhí)行:inotify_rsync_B.sh &這個方案的優(yōu)點:不會根據(jù)inotify輸出重復觸發(fā)rsync同步。缺點:每次都是rsync完整同步,如果文件數(shù)量較大則對比時間會比較長。inotify優(yōu)化inotify檢查磁盤變動是有隊列等值的配置的,inotify默認內(nèi)核參數(shù)值太小,會導致實際檢測的時候報錯。查看系統(tǒng)默認參數(shù)值sysctl -a | grep max_queued_eventssysctl -a | grep max_user_watchessysctl -a | grep max_user_instances臨時修改sysctl -w fs.inotify.max_queued_events="99999999"sysctl -w fs.inotify.max_user_watches="99999999"sysctl -w fs.inotify.max_user_instances="65535"固定修改:vim /etc/sysctl.conf #添加以下代碼fs.inotify.max_queued_events=99999999fs.inotify.max_user_watches=99999999fs.inotify.max_user_instances=65535
腳本編程, 系統(tǒng)運維, WordPress技巧新版Linux/vps本地十五天循環(huán)備份和七牛遠程備份腳本
最新在新建一個博客,新的博客是建在云服務器的,完全自主,不得不說感覺非常好,比起虛擬主機可操作性強太多了。因為可操作性強,所以想把該做的都做好,比如備份。受張戈博客影響,看到了張戈的同步7天的那篇文章,想照著操作的時候發(fā)現(xiàn),七牛的qrsync工具竟已廢棄:qrsync已廢棄看這簡介,推薦使用qshell命令行工具,先森就干脆研究下使用新的工具來同步。有段時間沒和七牛云儲存打交道了,變化還是挺大的。為七牛的推陳出新點個贊。一、數(shù)據(jù)庫、網(wǎng)站本地備份腳本在服務器上編輯shell腳本,腳本代碼如下:#!/bin/bash# Name:liuxxbak.sh# This is a ShellScript For Auto Backup and Delete old Backup# Date:2017-8-19source /etc/profilebackupdir=/web/data/liuxx_bak # 本地備份路徑time=` date +%Y%m%d `date=` date +"%Y-%m-%d %H:%M:%S" `day=15 #本地備份保留天數(shù)# 數(shù)據(jù)庫信息user=rootpassword=******host=127.0.0.1port=3306databases=wordpress# 本地網(wǎng)站根目錄backhome=/web/data/html/if [ ! -d $backupdir ]; then mkdir $backupdirfi mysqldump -h $host -P $post -u $user -p$password ${data} | gzip > $backupdir/${data}_$time.sql.gzif [ "$?" == 0 ];then echo "[${date}] 數(shù)據(jù)庫 ${data} 備份成功!!" >> ${backupdir}/mysqllog.logelse#備份失敗則進行以下操作 echo "[${date}] 數(shù)據(jù)庫 ${data} 備份失敗!!" >> ${backupdir}/mysqllog.logfi# 備份網(wǎng)站tar -zcvf $backupdir/liuxx_${time}.tar.gz $backhome > /dev/null 2>&1# 刪除同步find $backupdir -name "*.gz" -type f -mtime +${day} -exec rm {} \; > /dev/null 2>&1先森將以上代碼保存為‘liuxxbak.sh’,名稱可以隨意自定義。保存后需要增加可執(zhí)行權(quán)限:chmod +x liuxxbak.sh使用說明:將以上內(nèi)容變量按需修改:backupdir=本地備份絕對路徑day=本地備份保留天數(shù)user=數(shù)據(jù)庫用戶名(建議使用root用戶,出錯可能性小)password=數(shù)據(jù)庫密碼host=數(shù)據(jù)庫IP或域名port=數(shù)據(jù)庫端口databases=數(shù)據(jù)庫名稱backhome=本地網(wǎng)站根目錄腳本執(zhí)行方式:./liuxxbak.sh或者/web/data/liuxxbak.sh # 絕對路徑執(zhí)行如此可以檢查一下是否能夠成功備份。二、遠程備份到七牛云儲存1.命令。首先下載qshell命令行工具,下載頁面:根據(jù)服務器類型選擇下載linux 64位的服務器可以直接在服務器上這樣下載并增加可執(zhí)行權(quán)限:wget -O qshell http://devtools.qiniu.com/2.1.3/qshell-linux-x64 && chmod +x qshell可以將qshell命令放入自定義目錄。或直接放至/usr/bin/路徑下,這樣就可以任何地方直接輸入命令了。2.鑒權(quán)。有了命令之后,我們需要七牛的鑒權(quán),否則沒法使用接下來的命令。需要鑒權(quán)的命令都需要依賴七牛賬號下的 AccessKey 和 SecretKey。所以這類命令運行之前,需要使用 account 命令來設置下 AccessKey ,SecretKey 。鑒權(quán)的方式很簡單,首先進入七牛的個人中心->密鑰管理中,找到AccessKey 和 SecretKey。然后在服務器中運行一下命令:/web/data/qshell account ak sk執(zhí)行之后,用戶的所有信息寫入到磁盤$HOME_DIR/.qshell下面。如:root用戶執(zhí)行后,信息會保存在/root/.qshell/account.json文件中。如果你修改了密鑰,只需要重新執(zhí)行以上命令即可,配置信息將被覆蓋。3.同步。終于到了這一步。qshell命令的命令有很多,同步需要用到的命令是qupload。qupload是用來將本地目錄中的文件同步到七牛空間中的命令。命令格式:qshell qupload [<ThreadCount>] <LocalUploadConfig>ThreadCount:并發(fā)上傳的協(xié)程數(shù)量,默認為1,即文件一個個上傳,對于大量小文件來說,可以通過提高該參數(shù)值來提升同步速度。LocalUploadConfig:數(shù)據(jù)同步的配置文件,該配置文件里面包含了一些諸如本地同步目錄,目標空間名稱等信息。ThreadCount是可以忽略的參數(shù),默認一個文件一個文件的上傳,因為是要備份數(shù)據(jù)庫和本地網(wǎng)站文件,文件較少且大,顧保持默認就好。LocalUploadConfig為配置文件,配置文件中可帶的參數(shù)共有21個,先森選用了其中的7個。詳細的配置介紹請看這里。先森選用的參數(shù)如下,將以下內(nèi)容保存到文件‘localupload.cnf’:{ "src_dir" : "/web/data/liuxx_bak", "bucket" : "liuxx-backup", "ignore_dir" : true, "overwrite" : true, "check_exists" : true, "check_hash" : true, "rescan_local" : true}解釋,*為必須項:"src_dir":"/web/data/liuxx_bak", # 本地備份路徑*"bucket":"liuxx-backup", #同步數(shù)據(jù)的目標空間名稱,可以為公開空間或私有空間*"ignore_dir":true, #遠程同步到七牛時,忽略本地路徑"overwrite":true, #覆蓋同名文件"check_exists":true, #上傳前檢查是否有同名文件"check_hash":true, #在check_exists設置為true的情況下生效,是否檢查本地文件hash和空間文件hash一致"rescan_local":true, #檢測本地新增文件并同步最后,遠程同步到七牛云儲存的命令為:/web/data/qshell qupload /web/data/localupload.cnf可以執(zhí)行一下上面的命令,檢查是否能夠成功同步。先森同步到七牛云的效果:同步效果三、定時備份同步準備工作已經(jīng)完畢了,現(xiàn)在所需的就是每天的自動備份及遠程備份了。執(zhí)行crontab -e添加以下內(nèi)容:00 02 * * * /web/data/liuxxbak.sh30 02 * * * /web/data/qshell qupload /web/data/localupload.cnf >/dev/null 2>&1凌晨兩點執(zhí)行本地備份,凌晨兩點半執(zhí)行遠程備份。當然,你也可以將qshell命令加到liuxxbak.sh腳本的最后,那么只用添加第一條計劃任務就可以了。四、七牛十五天循環(huán)備份七牛云儲存免費的存儲空間大小是10G,如果你的七牛云存儲空間有點緊急的話,可以繼續(xù)本操作。這時候,點擊‘生命周期’,添加規(guī)則,我們可以設定刪除15天前的文件。先森設定的規(guī)則如下:刪除15天前的文件當然,如果七牛云存儲的剩余空間很足的話,可以保留更多天,這樣可供回退的版本就更多了。總結(jié)無論是用虛擬主機,還是使用云服務器,有一套備份的機制是很重要的。如果像先森一樣,主站使用的是虛擬主機,也有另外的云服務器的話,這套備份方案改改,也可以把自己虛擬主機的數(shù)據(jù)庫一起備份起來嘛。
系統(tǒng)運維, 經(jīng)驗雜筆溯源:mysql導入導出文件報錯ERROR 1290 (HY000):–secure-file-priv
近期遇到mysql導出文件的錯誤,之前遇到這個錯誤,因為需要導出的數(shù)據(jù)少,所以直接將結(jié)果手動復制。mysql> select * from childrenzone_order into outfile '/tmp/test.txt' fields terminated by ',' optionally enclosed by '"' escaped by '"' lines terminated by '\r\n';ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement但后來遇到大量的數(shù)據(jù)需要導出,簡單的復制就不能滿足需求了。進行百度,發(fā)現(xiàn)解決方法很簡單,在配置文件里增加配置,重啟Mysql即可。只是,生產(chǎn)環(huán)境中,數(shù)據(jù)庫是不能隨意重啟的,所以這個問題就很麻煩了。為了避免往后出現(xiàn)這種問題,先森覺得有必要研究清楚這個問題究竟影響了多少Mysql。解決方法首先是解決此類問題的方法,通過secure_file_priv 來完成對導入|導出的限制。secure_file_priv是在 /etc/my.cnf 中的[mysqld]下配置,共有三種限制方式。1、限制mysqld 不允許導入 | 導出:secure_file_priv = null2、限制mysqld 的導入 | 導出 只能發(fā)生在指定目錄下,如/tmp目錄:secure_file_priv = /tmp3、不對mysqld 的導入 | 導出做限制,有兩種書寫方式:secure_file_priv = /或secure_file_priv =而查詢secure_file_priv的方式如下:mysql> show variables like '%secure%';查詢secure_file_priv變量配置secure_file_priv變量配置的默認值為“NULL”,也就是默認不允許導入導出。溯源雖然知道了解決方法,但是前文也提到過,生產(chǎn)環(huán)境的Mysql并不能隨意的重啟,即使有主備。所以,弄明白受到默認禁止導入導出的Mysql版本有哪些就有必要了。通過查詢官方文檔,先森找到了影響版本,見下圖(點擊放大)。官方文檔變量介紹通過上圖可以看到,最后一個被紅框框選的文字:“Before MySQL 5.5.53, this variable is empty by default.(在MySQL 5.5.53,這個變量默認是空的。)”。這個變量在Mysql 5.5.53之后新增了“NULL”的配置,且默認為“NULL”。所以,如果發(fā)現(xiàn)自己的Mysql版本是5.5.53以后的,且不想限制導入導出的話,最好把變量的值配置好后擇時重啟Mysql。另外,上圖還介紹了,secure_file_priv這個變量是全局變量,且不能動態(tài)修改。這也是必須寫入配置文件并重啟Mysql的原因。
腳本編程, 系統(tǒng)運維, 經(jīng)驗雜筆Linux:sed的命令中插入變量的方法
先森近期接到個任務,這個任務中一項是需要每個服務器都得有自己的主機名,而不是默認的“l(fā)ocalhost”。因為是CentOS 6的操作系統(tǒng),所以需要改的文件有兩個,且為了不用重啟才生效,還要用hostname這個命令指定主機名。hostname命令用于顯示和設置系統(tǒng)的主機名稱。環(huán)境變量HOSTNAME也保存了當前的主機名。在使用hostname命令設置主機名后,系統(tǒng)并不會永久保存新的主機名,重新啟動機器之后還是原來的主機名。如果需要永久修改主機名,需要同時修改/etc/hosts和/etc/sysconfig/network的相關內(nèi)容。如果每臺服務器都去手動修改這兩個文件和執(zhí)行hostname命令未免太過麻煩,所以先森寫了一個簡單的腳本。想用“./腳本名 主機名”的方式修改主機名,但是實現(xiàn)腳本的過程中發(fā)生了一點小問題。hostname=$1sed -i 's/HOSTNAME=.*/HOSTNAME=$hostname/g' /etc/sysconfig/network先森想用sed命令用指定的變量值來替換“HOSTNAME=”后面指定的值,但執(zhí)行后發(fā)現(xiàn),等號后面的值變成了$符號+變量名稱,也就是sed命令中不認這個變量。后來經(jīng)過百度一番,找到了答案:“因為 hostname 是shell變量而不是sed中的變量,需要單獨拿到 sed 的單引號外面來才能被 shell 解析。單引號里面是 sed 的勢力范圍,shell 無法觸及。”sed的參數(shù)后的命令,是已單引號開始,單引號結(jié)束的,所以想將shell變量拿出來,那就在變量前面加個單引號讓sed命令結(jié)束,再在變量后面再加個單引號讓sed命令再開始,已就是這樣:hostname=$1sed -i 's/HOSTNAME=.*/HOSTNAME='$hostname'/g' /etc/sysconfig/network感覺這種代碼的編輯模式很眼熟,一下就想到了在HTML里面寫PHP的樣子:<?php if (is_home()){ ?> </body> <?php } ?>寫腳本突然有點寫PHP的感覺,著實讓先森覺得有點新鮮。下面貼下修改CentOS 6系統(tǒng)的主機名腳本。#!/bin/bash[ $# != 1 ] && echo "請指定主機名:./hostname.sh 主機名" && exit 1hostname=$1echo 127.0.0.1 ${hostname} >> /etc/hostssed -i 's/HOSTNAME=.*/HOSTNAME='$hostname'/g' /etc/sysconfig/networkhostname ${hostname}hostname.sh
系統(tǒng)運維, 經(jīng)驗雜筆原來TCP 協(xié)議可以這樣容易懂
在運維工作中,經(jīng)常接觸到網(wǎng)絡,所以先森今天看到這篇文章覺得寫得不錯,轉(zhuǎn)載過來自用。一、TCP 協(xié)議的作用互聯(lián)網(wǎng)由一整套協(xié)議構(gòu)成。TCP 只是其中的一層,有著自己的分工。(圖片說明:TCP 是以太網(wǎng)協(xié)議和 IP 協(xié)議的上層協(xié)議,也是應用層協(xié)議的下層協(xié)議。)最底層的以太網(wǎng)協(xié)議(Ethernet)規(guī)定了電子信號如何組成數(shù)據(jù)包(packet),解決了子網(wǎng)內(nèi)部的點對點通信。(圖片說明:以太網(wǎng)協(xié)議解決了局域網(wǎng)的點對點通信。)但是,以太網(wǎng)協(xié)議不能解決多個局域網(wǎng)如何互通,這由 IP 協(xié)議解決。(圖片說明:IP 協(xié)議可以連接多個局域網(wǎng)。)IP 協(xié)議定義了一套自己的地址規(guī)則,稱為 IP 地址。它實現(xiàn)了路由功能,允許某個局域網(wǎng)的 A 主機,向另一個局域網(wǎng)的 B 主機發(fā)送消息。(圖片說明:路由器就是基于 IP 協(xié)議。局域網(wǎng)之間要靠路由器連接。)路由的原理很簡單。市場上所有的路由器,背后都有很多網(wǎng)口,要接入多根網(wǎng)線。路由器內(nèi)部有一張路由表,規(guī)定了 A 段 IP 地址走出口一,B 段地址走出口二,......通過這套"指路牌",實現(xiàn)了數(shù)據(jù)包的轉(zhuǎn)發(fā)。(圖片說明:本機的路由表注明了不同 IP 目的地的數(shù)據(jù)包,要發(fā)送到哪一個網(wǎng)口(interface)。)IP 協(xié)議只是一個地址協(xié)議,并不保證數(shù)據(jù)包的完整。如果路由器丟包(比如緩存滿了,新進來的數(shù)據(jù)包就會丟失),就需要發(fā)現(xiàn)丟了哪一個包,以及如何重新發(fā)送這個包。這就要依靠 TCP 協(xié)議。簡單說,TCP 協(xié)議的作用是,保證數(shù)據(jù)通信的完整性和可靠性,防止丟包。二、TCP 數(shù)據(jù)包的大小以太網(wǎng)數(shù)據(jù)包(packet)的大小是固定的,最初是1518字節(jié),后來增加到1522字節(jié)。其中, 1500 字節(jié)是負載(payload),22字節(jié)是頭信息(head)。IP 數(shù)據(jù)包在以太網(wǎng)數(shù)據(jù)包的負載里面,它也有自己的頭信息,最少需要20字節(jié),所以 IP 數(shù)據(jù)包的負載最多為1480字節(jié)。(圖片說明:IP 數(shù)據(jù)包在以太網(wǎng)數(shù)據(jù)包里面,TCP 數(shù)據(jù)包在 IP 數(shù)據(jù)包里面。)TCP 數(shù)據(jù)包在 IP 數(shù)據(jù)包的負載里面。它的頭信息最少也需要20字節(jié),因此 TCP 數(shù)據(jù)包的最大負載是 1480 - 20 = 1460 字節(jié)。由于 IP 和 TCP 協(xié)議往往有額外的頭信息,所以 TCP 負載實際為1400字節(jié)左右。因此,一條1500字節(jié)的信息需要兩個 TCP 數(shù)據(jù)包。HTTP/2 協(xié)議的一大改進, 就是壓縮 HTTP 協(xié)議的頭信息,使得一個 HTTP 請求可以放在一個 TCP 數(shù)據(jù)包里面,而不是分成多個,這樣就提高了速度。(圖片說明:以太網(wǎng)數(shù)據(jù)包的負載是1500字節(jié),TCP 數(shù)據(jù)包的負載在1400字節(jié)左右。)三、TCP 數(shù)據(jù)包的編號(SEQ)一個包1400字節(jié),那么一次性發(fā)送大量數(shù)據(jù),就必須分成多個包。比如,一個 10MB 的文件,需要發(fā)送7100多個包。發(fā)送的時候,TCP 協(xié)議為每個包編號(sequence number,簡稱 SEQ),以便接收的一方按照順序還原。萬一發(fā)生丟包,也可以知道丟失的是哪一個包。第一個包的編號是一個隨機數(shù)。為了便于理解,這里就把它稱為1號包。假定這個包的負載長度是100字節(jié),那么可以推算出下一個包的編號應該是101。這就是說,每個數(shù)據(jù)包都可以得到兩個編號:自身的編號,以及下一個包的編號。接收方由此知道,應該按照什么順序?qū)⑺鼈冞€原成原始文件。(圖片說明:當前包的編號是45943,下一個數(shù)據(jù)包的編號是46183,由此可知,這個包的負載是240字節(jié)。)四、TCP 數(shù)據(jù)包的組裝收到 TCP 數(shù)據(jù)包以后,組裝還原是操作系統(tǒng)完成的。應用程序不會直接處理 TCP 數(shù)據(jù)包。對于應用程序來說,不用關心數(shù)據(jù)通信的細節(jié)。除非線路異常,收到的總是完整的數(shù)據(jù)。應用程序需要的數(shù)據(jù)放在 TCP 數(shù)據(jù)包里面,有自己的格式(比如 HTTP 協(xié)議)。TCP 并沒有提供任何機制,表示原始文件的大小,這由應用層的協(xié)議來規(guī)定。比如,HTTP 協(xié)議就有一個頭信息Content-Length,表示信息體的大小。對于操作系統(tǒng)來說,就是持續(xù)地接收 TCP 數(shù)據(jù)包,將它們按照順序組裝好,一個包都不少。操作系統(tǒng)不會去處理 TCP 數(shù)據(jù)包里面的數(shù)據(jù)。一旦組裝好 TCP 數(shù)據(jù)包,就把它們轉(zhuǎn)交給應用程序。TCP 數(shù)據(jù)包里面有一個端口(port)參數(shù),就是用來指定轉(zhuǎn)交給監(jiān)聽該端口的應用程序。(圖片說明:系統(tǒng)根據(jù) TCP 數(shù)據(jù)包里面的端口,將組裝好的數(shù)據(jù)轉(zhuǎn)交給相應的應用程序。上圖中,21端口是 FTP 服務器,25端口是 SMTP 服務,80端口是 Web 服務器。)應用程序收到組裝好的原始數(shù)據(jù),以瀏覽器為例,就會根據(jù) HTTP 協(xié)議的Content-Length字段正確讀出一段段的數(shù)據(jù)。這也意味著,一次 TCP 通信可以包括多個 HTTP 通信。五、慢啟動和 ACK服務器發(fā)送數(shù)據(jù)包,當然越快越好,最好一次性全發(fā)出去。但是,發(fā)得太快,就有可能丟包。帶寬小、路由器過熱、緩存溢出等許多因素都會導致丟包。線路不好的話,發(fā)得越快,丟得越多。最理想的狀態(tài)是,在線路允許的情況下,達到最高速率。但是我們怎么知道,對方線路的理想速率是多少呢?答案就是慢慢試。TCP 協(xié)議為了做到效率與可靠性的統(tǒng)一,設計了一個慢啟動(slow start)機制。開始的時候,發(fā)送得較慢,然后根據(jù)丟包的情況,調(diào)整速率:如果不丟包,就加快發(fā)送速度;如果丟包,就降低發(fā)送速度。Linux 內(nèi)核里面設定了(常量TCP_INIT_CWND),剛開始通信的時候,發(fā)送方一次性發(fā)送10個數(shù)據(jù)包,即"發(fā)送窗口"的大小為10。然后停下來,等待接收方的確認,再繼續(xù)發(fā)送。默認情況下,接收方每收到兩個TCP 數(shù)據(jù)包,就要發(fā)送一個確認消息。"確認"的英語是 acknowledgement,所以這個確認消息就簡稱 ACK。ACK 攜帶兩個信息:·期待要收到下一個數(shù)據(jù)包的編號·接收方的接收窗口的剩余容量發(fā)送方有了這兩個信息,再加上自己已經(jīng)發(fā)出的數(shù)據(jù)包的最新編號,就會推測出接收方大概的接收速度,從而降低或增加發(fā)送速率。這被稱為"發(fā)送窗口",這個窗口的大小是可變的。(圖片點擊放大)(圖片說明:每個 ACK 都帶有下一個數(shù)據(jù)包的編號,以及接收窗口的剩余容量。雙方都會發(fā)送 ACK。)注意,由于 TCP 通信是雙向的,所以雙方都需要發(fā)送 ACK。兩方的窗口大小,很可能是不一樣的。而且 ACK 只是很簡單的幾個字段,通常與數(shù)據(jù)合并在一個數(shù)據(jù)包里面發(fā)送。(圖片說明:上圖一共4次通信。第一次通信,A 主機發(fā)給B 主機的數(shù)據(jù)包編號是1,長度是100字節(jié),因此第二次通信 B 主機的 ACK 編號是 1 + 100 = 101,第三次通信 A 主機的數(shù)據(jù)包編號也是 101。同理,第二次通信 B 主機發(fā)給 A 主機的數(shù)據(jù)包編號是1,長度是200字節(jié),因此第三次通信 A 主機的 ACK 是201,第四次通信 B 主機的數(shù)據(jù)包編號也是201。)即使對于帶寬很大、線路很好的連接,TCP 也總是從10個數(shù)據(jù)包開始慢慢試,過了一段時間以后,才達到最高的傳輸速率。這就是 TCP 的慢啟動。六、數(shù)據(jù)包的遺失處理TCP 協(xié)議可以保證數(shù)據(jù)通信的完整性,這是怎么做到的?前面說過,每一個數(shù)據(jù)包都帶有下一個數(shù)據(jù)包的編號。如果下一個數(shù)據(jù)包沒有收到,那么 ACK 的編號就不會發(fā)生變化。舉例來說,現(xiàn)在收到了4號包,但是沒有收到5號包。ACK 就會記錄,期待收到5號包。過了一段時間,5號包收到了,那么下一輪 ACK 會更新編號。如果5號包還是沒收到,但是收到了6號包或7號包,那么 ACK 里面的編號不會變化,總是顯示5號包。這會導致大量重復內(nèi)容的 ACK。如果發(fā)送方發(fā)現(xiàn)收到三個連續(xù)的重復 ACK,或者超時了還沒有收到任何 ACK,就會確認丟包,即5號包遺失了,從而再次發(fā)送這個包。通過這種機制,TCP 保證了不會有數(shù)據(jù)包丟失。(圖片說明:Host B 沒有收到100號數(shù)據(jù)包,會連續(xù)發(fā)出相同的 ACK,觸發(fā) Host A 重發(fā)100號數(shù)據(jù)包。)(完)
系統(tǒng)運維, 經(jīng)驗雜筆CentOS 7中的Nginx控制腳本
先森安裝Nginx都是編譯安裝,所以不像yum安裝的自帶控制腳本,也就是不能通過service nignx start這種方式啟動Nginx。不過在CentOS 6中,Nginx的啟動腳本早已備好,增加控制腳本輕輕松松。不過,先森公司的客戶要求新的服務器全用CentOS 7的操作系統(tǒng),如此一來,先森之前的控制腳本就沒用了。雖然先森當初培訓的時候?qū)W習的就是RedHat 7,但是參加工作以來,一直使用的CentOS 6的操作系統(tǒng),早已把7版本的命令習慣忘完。先森覺得,CentOS 6和CentOS 7的變化最明顯的就是控制服務啟動關閉的命令,由service換成了systemctl。雖然在CentOS 7中service命令依舊可以用,但是使用的效果已經(jīng)大打折扣了。在網(wǎng)上找了半天,想要找到與CentOS 6類似的控制腳本,用service啟動的,但是效果差強人意,甚至可以說無效。最后終于找到了使用systemctl的控制腳本,下面分享一波。控制腳本第一步:編輯vim /usr/lib/systemd/system/nginx.service文件,添加以下內(nèi)容:注意要修改nginx的目錄,先森的是放在默認的/usr/local/nginx中。[Unit]Description=nginx - high performance web serverDocumentation=http://nginx.org/en/docs/After=network.target remote-fs.target nss-lookup.target[Service]Type=forkingPIDFile=/usr/local/nginx/logs/nginx.pidExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.confExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.confExecReload=/bin/kill -s HUP $MAINPIDExecStop=/bin/kill -s QUIT $MAINPIDPrivateTmp=true[Install]WantedBy=multi-user.target第二步:添加可執(zhí)行權(quán)限:chmod 755 /usr/lib/systemd/system/nginx.service第三步:添加開機啟動:systemctl enable nginx控制Nginx:systemctl start nginx # 啟動Nginxsystemctl stop nginx # 關閉Nginxsystemctl status nginx # 查看Nginx狀態(tài)總結(jié)唉,CentOS 7咋用咋不習慣,但是系統(tǒng)版本的升級總是大勢所趨,還是得慢慢習慣。運維的路,還很長。
系統(tǒng)運維, 經(jīng)驗雜筆解決VMware Workstation橋接模式無法聯(lián)網(wǎng)問題
因為工作原因,先森經(jīng)常會用到虛擬機做測試,然而也經(jīng)常遇到橋接模式?jīng)]有辦法聯(lián)網(wǎng),無法獲取IP地址的問題。以往先森的做法都是重啟VMware Workstation甚至重啟物理機,但這些往往都很誤事,所以先森決定好好找找問題原因,幸運的是,先森找到了問題所在。橋接模式獲取不到IP解決問題問題如上圖,重啟網(wǎng)絡會在獲取IP那一步等待很久(DHCP),然后報錯,查看IP可以看到eth0沒有IP地址。這種情況的原因可能是由于橋接模式橋接的網(wǎng)卡不正確,解決步驟如下。第一步,VMware中點擊“編輯”->“虛擬網(wǎng)絡編輯器”;虛擬網(wǎng)絡編輯器第二步VMware默認的橋接模式中橋接方式為“自動”,而自動,可能就將網(wǎng)絡橋接到其他網(wǎng)卡上去了,所以造成無法聯(lián)網(wǎng)。這時候第二步就是把橋接到的網(wǎng)卡選擇為物理機上網(wǎng)的網(wǎng)卡。點擊電腦右下角的網(wǎng)絡,再點擊“打開網(wǎng)絡和共享中心”,打開后選擇“更改適配器設置”。在連接網(wǎng)絡的適配器下面有網(wǎng)卡的名稱,如先森的是“本地連接”下的“Realtek PCIe GBE Family Controller”。這時候就將VMware的橋接模式橋接到“Realtek PCIe GBE Family Controller”這個網(wǎng)卡,點擊確認保存即可。更改橋接網(wǎng)卡設置第三步這時候再重啟網(wǎng)絡,即可獲取到IP地址。網(wǎng)絡恢復正常

川公網(wǎng)安備 51011202000104號