Showing posts with label linux. Show all posts

The Linux Boot Process

The Linux Boot Process

The Linux boot process consists of several stages each represented by a different component. The following list briefly summarizes the boot process and features all the major components involved.

  1. BIOS After the computer has been turned on, the BIOS initializes the screen and keyboard and tests the main memory. Up to this stage, the machine does not access any mass storage media. Subsequently, the information about the current date, time, and the most important peripherals are loaded from the CMOS values. When the first hard disk and its geometry are recognized, the system control passes from the BIOS to the boot loader.

  2. Boot Loader The first physical 512-byte data sector of the first hard disk is loaded into the main memory and the boot loader that resides at the beginning of this sector takes over. The commands executed by the boot loader determine the remaining part of the boot process. Therefore, the first 512 bytes on the first hard disk are referred to as the Master Boot Record (MBR). The boot loader then passes control to the actual operating system, in this case, the Linux kernel. More information about GRUB, the Linux boot loader, can be found in Section 15.0, The Boot Loader GRUB.

  3. Kernel and initramfs To pass system control, the boot loader loads both the kernel and an initial RAM–based file system (initramfs) into memory. The contents of the initramfs can be used by the kernel directly. initramfs contains a small executable called init that handles the mounting of the real root file system. If special hardware drivers are needed before the mass storage can be accessed, they must be in initramfs. For more information about initramfs, refer to Section 14.1.1, initramfs.

  4. init on initramfs This program performs all actions needed to mount the proper root file system, like providing kernel functionality for the needed file system and device drivers for mass storage controllers with udev. After the root file system has been found, it is checked for errors and mounted. If this has been successful, the initramfs is cleaned and the init program on the root file system is executed. For more information about init, refer to Section 14.1.2, init on initramfs. Find more information about udev in Section 17.0, Dynamic Kernel Device Management with udev.

  5. init init handles the actual booting of the system through several different levels providing different functionality. init is described in Section 14.2, The init Process.

14.1.1 initramfs

initramfs is a small cpio archive that the kernel can load to a RAM disk. It provides a minimal Linux environment that enables the execution of programs before the actual root file system is mounted. This minimal Linux environment is loaded into memory by BIOS routines and does not have specific hardware requirements other than sufficient memory. initramfs must always provide an executable named init that should execute the actual init program on the root file system for the boot process to proceed.

Before the root file system can be mounted and the operating system can be started, the kernel needs the corresponding drivers to access the device on which the root file system is located. These drivers may include special drivers for certain kinds of hard drives or even network drivers to access a network file system. The needed modules for the root file system may be loaded by init on initramfs. After the modules are loaded, udev provides the initramfs with the needed devices. Later in the boot process, after changing the root file system, it is necessary to regenerate the devices. This is done by boot.udev with the command udevtrigger.

If you need to change hardware (e.g. hard disks) in an installed system and this hardware requires different drivers to be present in the kernel at boot time, you must update initramfs. This is done in the same way as with its predecessor, initrd—by calling mkinitrd. Calling mkinitrd without any argument creates an initramfs. Calling mkinitrd -R creates an initrd. In openSUSE®, the modules to load are specified by the variable INITRD_MODULES in /etc/sysconfig/kernel. After installation, this variable is automatically set to the correct value. The modules are loaded in exactly the order in which they appear in INITRD_MODULES. This is only important if you rely on the correct setting of the device files /dev/sd?. However, in current systems you also may use the device files below /dev/disk/ that are sorted in several subdirectories, named by-id, by-path and by-uuid, and always represent the same disk. This is also possible at install time by specifying the respective mount option.

IMPORTANT: Updating initramfs or initrd

The boot loader loads initramfs or initrd in the same way as the kernel. It is not necessary to reinstall GRUB after updating initramfs or initrd, because GRUB searches the directory for the right file when booting.

14.1.2 init on initramfs

The main purpose of init on initramfs is to prepare the mounting of and access to the real root file system. Depending on your system configuration, init is responsible for the following tasks.

Loading Kernel Modules

Depending on your hardware configuration, special drivers may be needed to access the hardware components of your computer (the most important component being your hard drive). To access the final root file system, the kernel needs to load the proper file system drivers.

Providing Block Special Files

For each loaded module, the kernel generates device events. udev handles these events and generates the required block special files on a RAM file system in /dev. Without those special files, the file system and other devices would not be accessible.

Managing RAID and LVM Setups

If you configured your system to hold the root file system under RAID or LVM, init sets up LVM or RAID to enable access to the root file system later. Find information about RAID and LVM in Section 2.0, Advanced Disk Setup.

Managing Network Configuration

If you configured your system to use a network-mounted root file system (mounted via NFS), init must make sure that the proper network drivers are loaded and that they are set up to allow access to the root file system.

When init is called during the initial boot as part of the installation process, its tasks differ from those mentioned earlier:

Finding the Installation Medium

As you start the installation process, your machine loads an installation kernel and a special initrd with the YaST installer from the installation medium. The YaST installer, which is run in a RAM file system, needs to have information about the location of the installation medium to access it and install the operating system.

Initiating Hardware Recognition and Loading Appropriate Kernel Modules

As mentioned in Section 14.1.1, initramfs, the boot process starts with a minimum set of drivers that can be used with most hardware configurations. init starts an initial hardware scanning process that determines the set of drivers suitable for your hardware configuration. The names of the modules needed for the boot process are written to INITRD_MODULES in /etc/sysconfig/kernel. These names are used to generate a custom initramfs that is needed to boot the system. If the modules are not needed for boot but for coldplug, the modules are written to /etc/sysconfig/hardware/hwconfig-*. All devices that are described with configuration files in this directory are initialized in the boot process.

Loading the Installation System or Rescue System

As soon as the hardware has been properly recognized, the appropriate drivers have been loaded, and udev has created the device special files, init starts the installation system, which contains the actual YaST installer, or the rescue system.

Starting YaST

Finally, init starts YaST, which starts package installation and system configuration.

Linux忘记root密码怎么办[转]

在机器启动到grub进行操作系统选择时,

对于Redhat linux:

用上下键将光标放在linux系统上,按“e”

在有kernel那一行按“e”,输入“空格 single”,然后回车

按“b”,启动,系统会自动进入单用户模式,

使用passwd root命令,按提示输入新口令

修改口令后,输入reboot 命令重启系统即可

对于SUSE linux:

先按"esc"键,从grub的图形界面转至字符界面

然后,用上下键将光标放在linux系统上,按“e”

在有kernel那一行按“e”,输入“空格 1”,然后回车

按“B”启动,系统会自动进入“runlevel 1”。

然后执行“passwd”,按提示输入新口令

修改完口令后,输入reboot命令重启系统即可。

---------------------------------------------------------------------

一. lilo
1. 在出现 lilo: 提示时键入 linux single
画面显示 lilo: linux single
2. 回车可直接进入linux命令行
3. #vi /etc/shadow
将第一行,即以root开头的一行中root:后和下一个:前的内容删除,
第一行将类似于
root::......
保存
4. #reboot重启,root密码为空

二. grub
1. 在出现grub画面时,用上下键选中你平时启动linux的那一项(别选dos哟),然后按e键
2. 再次用上下键选中你平时启动linux的那一项(类似于kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/),然后按e键
3. 修改现在见到的命令行,有两种方法:
a.加入single,结果如下:
kernel /boot/vmlinuz-2.4.18-14 single ro root=LABEL=/
b.在行末加入run level,比如想进入run level 3,结果如下:
kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/ 3
由于是忘记root密码,则可进入run level 1,结果如下:
kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/ 1
4. 回车返回,然后按b键启动,即可直接进入linux命令行
5. #vi /etc/shadow
将第一行,即以root开头的一行中root:后和下一个:前的内容删除,
第一行将类似于
root::......
保存
6. #reboot重启,root密码为空
7. 这是网上的教程,但我实际操作时,老提示不能修改只读文件,于是先用chmod +w shadow命令将shadow文件改为可写。之前
所作的修改,留下了.shadow.swp文件,使用vi shadow就没有问题了。

另外还有一类,可能是比较老版本的linux,不得而知,方法如下:
  随着Linux的流行,越来越多的服务器上安装了Linux操作系统。但是问题也随之而来——忘记了服务器的密码怎么办?不用着急,使用下面介绍的三招杀手锏就可以使你在不重装Linux的情况下轻松解决密码问题。

  第一招:如果你的系统是通过LILO管理器启动的,可以在LILO启动提示符"LILO boot:"后输入"Linux single"(不包括两个双引号),回车后即可启动Linux系统进入单用户模式。这时候你就可以用passwd命令来修改你的密码了。修改完成后重新 启动系统就可以使用新的密码登录了。这一着在一些系统下行得通,但是在另一些系统下则行不通。这是你可以试试用第二招来清除Linux的密码。

  第二招:用安装系统时制作的boot盘启动,当出现"LILO boot:"提示符时输入"Linux mount =/dev/xxxx" (不包括两个双引号),其中xxxx代表Linux所在的分区。在Linux中,第一个IDE硬盘的设备名是hda,所以第一硬盘的第一分区为hda1, 第二分区为hda2,依此类推;第二个IDE硬盘的设备名是hdb,同理,第二硬盘的第一分区为hdb1,第二分区为hdb2,依此类推;如果你使用的是 SCSI硬盘,则第一硬盘的设备名是sda,第一硬盘的第一分区为sda1,第二分区为sda2,依此类推;第二个SCSI硬盘的设备名是sdb,则第二 硬盘的第一分区为sdb1,第二分区为sdb2,依此类推。正确输入硬盘的设备名及分区号后启动Linux,系统将自动把Linux的分区mount到 /mnt下。这时候你只要进入/mnt/etc下,用vi命令打开passwd文件,将root行中的密码去掉,退出并保存文件。然后重新引导系统后,在 超级用户下执行password命令,重新生成一个密码即可。这里需要注意一个问题:如果你的系统同时含有passwd和shadow两个文件,则需要修 改的密码文件是/mnt/etc下的shadow。因为shadow是passwd的一个映像,是真正存放密码的文件。如果你的Linux系统不能识 别"Linux mount =/dev/xxxx"命令也不要紧,我们还有第三招——通用方法来解决它。

  第三招:使用应急引导盘。目前各个版本的Linux都带有随盘发行的应急引导盘,一般有两张:一张是boot盘,另一张是root盘。这两张盘 一般是以img或gz格式的文件存放在光盘上,文件名各个版本都差不多,主文件名形如rescxxxx,扩展名是.img或.gz。我所使用的是 rescboot.img和rescroot.img。找到这两个文件后使用随盘附带的IMG文件写盘工具rawrite.exe将 rescboot.img和rescroot.img分别写入两张空白磁盘,然后使用这两张盘引导Linux。启动后在超级用户下执行如下命令:

  :mount/dev/xxxx/mnt
  #cd/mnt
  vi/mnt/etc/passwd

  然后将超级用户密码删除即可,删除方法同第二招。命令中的xxxx的含义与第二招中的相同。当然,如果你的系统同时含有passwd和shadow两个文件,则只需要修改/mnt/etc下的shadow即可解决问题。

terminal & console

终端(Terminal)
终端是用户和计算机进行实时交互的接口设备。终端一般由显示器、键盘和终端控制器组成,有的还带有鼠标。显示器和键盘与终端控制器相连,终端控制器通过通用端口(如串口)和计算机主机相连。用户通过终端和计算机交流。一台UNIX主机可以连多个终端。终端分为两类:字符终端和图形终端。
仿真终端 在某计算机上运行某一特定程序,把计算机当作另一台计算机的终端使用。目前仿真终端与UNIX主机的连接方式主要有网络连接和串口连接。

控制台(Console)
这是一种特殊的终端,由显示器、键盘(和鼠标)组成,分别连到主机的专用接口(监视器接口、键盘接口、鼠标接口)上。一般一台主机只能接一个控制台,控制台可以完成普通终端不能完成的工作:非常重要的信息(如严重的错误信息),只能在控制台上显示,有些特殊的任务(如执行修复工作)也只能在控制台上完成。除了实现以上特殊功能外,控制台还可以象其它终端那样工作。

echo与sudo

众所周知,使用 echo 并配合命令重定向是实现向文件中写入信息的快捷方式。本文介绍如何将 echo 命令与 sudo 命令配合使用,实现向那些只有系统管理员才有权限操作的文件中写入信息。

比如要向 test.asc 文件中随便写入点内容,可以:

$ echo "信息" > test.asc
# 或者
$ echo "信息" >> test.asc

下面,如果将 test.asc 权限设置为只有 root 用户才有权限进行写操作:

$ sudo chown root.root test.asc

然后,我们使用 sudo 并配合 echo 命令再次向修改权限之后的 test.asc 文件中写入信息:

$ sudo echo "又一行信息" >> test.asc
-bash: test.asc: Permission denied

这时,可以看到 bash 拒绝这么做,说是权限不够。这是因为重定向符号 “>” 和 ">>" 也是 bash 的命令。我们使用 sudo 只是让 echo 命令具有了 root 权限,但是没有让 “>” 和 ">>" 命令也具有 root 权限,所以 bash 会认为这两个命令都没有像 test.asc 文件写入信息的权限。

解决这一问题的途径有两种。第一种是利用 "sh -c" 命令,它可以让 bash 将一个字串作为完整的命令来执行,这样就可以将 sudo 的影响范围扩展到整条命令。具体用法如下:

$ sudo sh -c 'echo "又一行信息" >> test.asc'

另一种方法是利用管道和 tee 命令,该命令可以从标准输入中读入信息并将其写入标准输出或文件中,具体用法如下:

$ echo "第三条信息" | sudo tee -a test.asc

注意,tee 命令的 "-a" 选项的作用等同于 ">>" 命令,如果去除该选项,那么 tee 命令的作用就等同于 ">" 命令。

getty

bash: no job control in this shell

当 我们从shell, 启动一个跑在另外一个tty的shell时将会碰到这个提示。 最常见的是, shell直接把/dev/console作为它的标准输入输出。比如 gentoo, arch使用硬盘安装大法, 但是却找不到硬盘是, 它会自动启动一个shell, 这个shell就是没有job control的了。

至于原因, 涉及的内容比较多, 所以我就不想在这里作详细的分析了。想深入了解的话, 自己看看 AUPE就是了。 大致的原因是, 一个session leader试图打开一个终端设备时, 假如这个leader没有控制终端, 那么这个终端设备将自动成为改session leader的的控制终端。了解这一点就不难理解为什么会有这个提示了: 就是说shell没有找到控制终端。

解决的办法很简单: 使用agetty 来调用shell。 agetty会创建新的会话, 自然没有了控制终端。所以自然, agetty所打开的tty自动成为了它的控制终端, 并且被agetty调用shell也会继承这一点。

以下是一个例子:



#!/bin/sh

TMPNAME=`mktemp /tmp/bbsh.XXX`
echo '#!/bin/sh' > $TMPNAME
echo 'exec /bin/sh' >> $TMPNAME

chmod +x $TMPNAME

#请确保tty8 没有被其他程序正在使用
/sbin/agetty -l /tmp/bbsh 38400 tty8 linux
rm $TMPNAME

执行该脚本之后将在tty8, 运行一个agetty。 随意输入一个login name: 之后回车,
将看到一个shell, 并且这个shell是带有job control的。这样你就可以建一个更好的
minilinux了。

awk - 模式扫描与处理语言

1. 介绍

awk 是设计用来使很多常见的信息检索和文本操作任务易于陈述和进行的一门编程语言。

awk 的基本操作是依次扫描一组输入文件,查找匹配与用户已经指定的模式集合中的任何一个模式相匹配的行。对于每个模式,都可以指定一个动作;这个动作将在匹配这个模式每一行上进行。

尽管读者熟悉的 UNIX ® 程序 grep 也认可这种方式,在 awk 中的模式可能比 grep 中的模式更加一般性,而且允许的动作比只是打印匹配的行更加复杂。例如,awk 程序

{print $3, $2}

依次打印一个表格的第三和第二列。程序

$2 ~ /A|B|C/

打印在第二列是 A、B 或 C 的所有输入行。程序

$1 != prev { print; prev = $1 }

打印第一个字段不同于前面的第一个字段的所有的行。
1.1. 用法

命令

awk program [files]

在指名的一组文件上,或标准输入上、如果没有指定文件的话,执行字符串 program 中的 awk 命令。语句也可以放置到一个文件 pfile 中,并用如下命令执行。

awk -f pfile [files]

1.2. 程序结构

awk 程序是如下形式的语句序列:


模式 { 动作 }
模式 { 动作 }
...

输入的每行都要依次针对每个模式做匹配。对于每个匹配的模式,执行相关的动作。在所有模式都已经测试过了的时候,取回下一行并从头开始做匹配。

模式或动作二者都可以但不能同时省略。如果一个模式没有动作,简单的把匹配的行复制到输出。(所以匹配多个模式的行可能被打印多次)。如果一个动作没有模式,则这个动作在所有输入上进行。不匹配模式的行被忽略。

因为模式和动作都是可选的,动作必须被包围在花括号中来区别于模式。
1.3. 记录和字段

awk 输入被分解成了终止于记录分隔符的“记录”。缺省的记录分隔符是换行,所以缺省的 awk 一次处理它的输入中的一行。当前记录的数可在命名为 NR 的变量中得到。

每个输入记录被当作分解成了“字段”。字段通常用空白也就是空格或 tab 来分隔,但是输入字段分隔符是可以变更的,这在后面会有所描述。字段被引用为 $1、$2 ,以此类推。这里的 $1 是第一个字段,而 $0 是整个输入记录自身。字段可以被赋值。在当前记录中字段的数目可以在命名为 NF 的变量中得到。

变量 FS 和 RS 分别指定输入字段和记录分隔符;它们可以在任何时候被改变为任何的单一字符。也可以使用可选的命令行参数 −Fc 来设置 FS 为字符 c。

如果记录分隔符为空,把空输入行作为记录分隔符,并把空格、tab 和换行作为字段分隔符处理。

变量 FILENAME 包含当前输入文件的名字。
1.4. 打印

一个动作可以没有模式,在这种情况下动作在所有行上执行。最简单的动作是打印某些或所有的记录;这可以通过 awk 命令 print 来完成。awk 程序

{ print }

打印每个记录,也就是把输入完好的复制到输出。更有用的是打印来自每个记录的一个字段或某些字段。例如

print $2, $1

按逆序打印前两个字段。在 print 语句中用逗号分隔的项,在输出的时候会用当前输出字段分隔符分隔开。没有用逗号分隔的项会串联起来,所以

print $1 $2

把第一个和第二个字段合在一起。

可以使用预定义的变量 NF 和 NR;例如

{ print NR, NF, $0 }

打印出前导了记录数和字段数的每个记录。

输出可以被转向到多个文件中;程序

{ print $1 >"foo1"; print $2 >"foo2" }

写第一个字段 $1 到文件 foo1 中,写第二个字段到文件 foo2 中。还可以使用 >> 符号:

print $1 >>"foo"

添加输出到文件 foo。(在每种情况下,输出文件都在必要时建立)。文件名可以是一个变量或字段,同常量一样;例如

print $1 >$2

使用字段 2 的内容作为文件名字。

自然的,有对输出文件数目的限制,目前是 10 个。

类似的,输出可以用管道导入到(只在 UNIX 上的)其他进程;例如,

print | "mail bwk"

把输入邮递给 bwk。

可以使用变量 OFS 和 ORS 来改变当前输出字段分隔符和输出记录分隔符。输出记录分隔符被添加到 print 语句的输出后面。

awk 还提供 printf 语句用于输出格式化:

printf format expr, expr, ...

依据在 format 中的规定格式化在列表中的表达式并打印它们。例如,

printf "%8.2f %10ld\n", $1, $2

打印 $1 为 8 位宽的小数点后有两位的浮点数,打印 $2 为 10 位长的长十进制数,并跟随着一个换行。不自动生成输出分隔符;你必须自己增加它们,如这个例子那样。这个版本的 printf 同于 C 语言所使用的。
2. 模式

在动作之前的模式充当决定一个动作是否执行的选择者。有多种多样的表达式可以被用做模式: 正则表达式,算术关系表达式,字符串值的表达式,和它们的任意的布尔组合。
2.1. BEGIN 和 END

特殊模式 BEGIN 匹配输入的开始,在第一个记录被读取之前。模式 END 匹配输入的结束,在最后一个记录已经被处理之后。BEGIN 和 END 从而提供了在处理之前和之后获得控制的方式,用来做初始化和总结。

作为一个例子,可以如下这样把字段分隔符设置为冒号

BEGIN { FS = ":" }
... 余下的程序 ...

或如下这样输出输入行的计数

END { print NR }

如果 BEGIN 出现,它必须是第一模式;END 必须是最后一个模式,如果用到了的话。
2.2. 正则表达式

最简单的正则表达式是包围在斜杠内的文字的字符串,如

/smith/

这实际上是个完整的 awk 程序,它将打印包含名字“smith”的任何出现的所有行。如果一行包含“smith”作为一个大单词的一部分,它也会被打印,比如

blacksmithing

awk 正则表达式包括在 UNIX 文本编辑器 ed 和 grep 中能找到的正则表达式形式(没有后引用)。此外同 lex 一样,awk 允许采用圆括号用做组合,| 用做选择,+ 用做“一或多个”,? 用于“零或一个”。字符类可以简写: [a−zA−Z0−9] 是所有字母和数字的集合。作为例子,awk 程序

/[Aa]ho|[Ww]einberger|[Kk]ernighan/

将打印包含名字“Aho”、“Weinberger”或“Kernighan”中任何一个、不论首字母是否大写的所有行。

(带有上述扩展的)正则表达式必须包围在斜杠中,同 ed 和 sed 一样。在正则表达式内,空白和正则表达式元字符是有意义的。要去掉某个正则表达式字符的特殊意义,可前导一个反斜杠。一个例子模式

/\/.*\//

它匹配包围在斜杠内的任何字符串。

你还可以通过算符 ~ 和 !~ 指定任何字段或变量匹配(或不匹配)一个正则表达式。程序

$1 ~ /[jJ]ohn/

打印第一个字段匹配“john”或“John”的所有行。注意它还会匹配“Johnson” 和“St. Johnsbury”等等。要精确的限制它为 [jJ]ohn,使用

$1 ~ /^[jJ]ohn$/

这个脱字符号 ^ 指称一行或一个字段的开始处;美元号 $ 指称结束处。
2.3. 关系表达式

awk 模式可以是涉及常用的关系算符 <、<=、==、!=、>=、> 的关系表达式。 例子

$2 > $1 + 100

它选择第二个字段至少比第一个字段大 100 的行。类似的

NF % 2 == 0

打印有偶数个字段的行。

在关系测试中,如果操作数(operand)都不是数值,则做字符串比较;否则做数值比较。所以

$1 >= "s"

选择开始于 s、t、u 等字符的行。在缺乏任何其他信息的情况下,字段被当作字符串,所以程序

$1 > $2

将进行字符串比较。
2.4. 模式的组合

模式可以是模式的使用算符 ||(或)、&&(与)和 !(非)的任意布尔组合。例如

$1 >= "s" && $1 < "t" && $1 != "smith" 选择第一字段开始于“s”而不是“smith”的行。&& 和 || 保证它们的操作数会被从左至右的求值;在确定了真或假之后求值立即停止。 2.5. 模式范围 选择一个动作的“模式”还可以由用逗号分隔的两个模式组成,比如 pat1,{ ... } pat2 在这种情况下,这个动作在 pat1 的一个出现和 pat2 的下一个出现之间(包含它们)的每个行上进行。例如, /start/, /stop/ 打印在 start 和 stop 之间的所有行。而 NR == 100, NR == 200 { ... } 在输入的从 100 到 200 的行上进行这个动作。 3. 动作 awk 动作是用换行或分号终止的动作语句的序列。这些动作语句可以被用来做各种各样的簿记和字符串操纵任务。 3.1. 内置函数 awk 提供了一个“长度”函数来计算字符串的长度。下面这个程序打印每个记录,每个都前导它的长度: {print length, $0} length 自身是个“伪变量”,它生成当前记录的长度;length(参数)生成它的参数的长度,下面的程序等价于上个程序 {print length($0), $0} 参数可以是任何表达式。 awk 还提供算术函数 sqrt、log、exp 和 int,分别得到它们参数的平方根、自然对数、指数和整数部分。 某个内置函数的名字,不带有参数或圆括号,表示这些函数在整个记录上的值。程序 length <> 20

打印长度小于 10 或大于 20 的行。

函数 substr(s, m, n) 生成 s 的开始于位置 m(起始于 1)的最多 n 个字符长的子串。如果省略了 n,子串到达 s 的结束处。函数 index(s1, s2) 返回字符串 s2 在 s1 出现的位置,如果未出现则为零。

函数 sprintf(f, e1, e2, ...) 在 f 指定的 printf 格式中生成表达式 e1、e2 等的值。所以例子

x = sprintf("%8.2f %10ld", $1, $2)

设置 x 为格式化 $1 和 $2 的值所生成的字符串。
3.2. 变量、表达式和赋值

awk 变量依据上下文而被接纳为数值(浮点数)或字符串值。例如

x = 1

x 明显的是个数,而

x = "smith"

明显的是个字符串。在上下文需要的时候,把字符串转换为数或反之。例如

x = "3" + "4"

把 7 赋值给 x。在数值上下文中,不能被解释为数的字符串一般会有为零的数值,但是依靠这种行为是愚蠢的。

缺省的,(不是内置的)变量被初始化为空字符串,它有为零的数值;这消除了大多数对 BEGIN 段落的需要。例如,前两个字段的总和可以用下列程序计算

{ s1 += $1; s2 += $2 }
END { print s1, s2 }

算术在内部以浮点数的方式计算。算术算符有 +、-、*、/、%(模)。C 语言的增加 ++ 和减少 −− 算符也可用,还有赋值算符 +=、-=、*=、/=、%=。这些算符都可以用于表达式中。
3.3. 字段变量

awk 中的字段在本质上享有变量的所有性质 — 他们可以用在算术或字符串运算/操作中,并可以被赋值。所以你可以把第一个字段替代为一个序号,比如:

{ $1 = NR; print }

或累计前两个字段到第三个字段中,比如:

{ $1 = $2 + $3; print $0 }

或把一个字符串赋值到一个字段:

{ if ($3 > 1000)
$3 = "too big"
print
}

它把第三个字段替代为“too big”,在它很长的时候,并在这种情况下,打印这个记录。

字段引用可以是数值表达式,比如

{ print $i, $(i+1), $(i+n) }

一个字段被认为是数值还是字符串依赖于上下文;在有歧义的情况下比如

if ($1 == $2) ...

字段被当作字符串。

每个输入行都在需要的时候被自动分解到字段。还可以把任意变量或字段分解到字段:

n = split(s, array, sep)

把字符串 s 分解到 array[1], ..., array[n]。返回找到的元素数目。如果提供了 sep 参数,则把它用做字段分隔符;否则使用 FS 作为分隔符。
3.4. 字符串连接

字符串可以被串接。例如

length($1 $2 $3)

返回前三个字段的长度。还有在 print 语句中

print $1 " is " $2

打印用“ is ”分隔的两个字段。变量和数值表达式也可以在连接中出现。
3.5. 数组

数组元素不用声明;在被提及到的时候才导致它的存在。下标可以有任何非空的值,包括非数值的字符串。作为常规的数值下标的例子,语句

x[NR] = $0

把当前输入记录赋值到数组 x 的第 NR 个元素。实际上,在原理上(尽管可能很慢)用 awk 程序按随机的次序处理整个输入是可能的

{ x[NR] = $0 }
END { ... 程序 ... }

第一动作只是把每个输入行记录到数组 x 中。

数组元素可以用非数值的值来命名,这给予 awk 非常象 Snobol 语言的关联内存表的能力。假设输入包含的字段带有象 apple、orange 等等这样的值。则程序

/apple/ { x["apple"]++ }
/orange/ { x["orange"]++ }
END { print x["apple"], x["orange"] }

增加指名的数组元素的计数,并在输入结束时打印它们。
3.6. 控制流语句

awk 提供了同 C 语言一样的基本控制流语句 if-else、while、for,和使用花括号的语句组合。我们在章节 3.3 展示了 if 语句而没有描述它。求值在圆括号中的条件;如果为真,则执行在跟随在 if 后面的语句。else 部分是可选的。

while 语句完全同 C 语言的一样。例如,要一行一个打印所有输入字段

i = 1
while (i <= NF) { print $i ++i } for 语句也完全同 C 的一样: for (i = 1; i <= NF; i++) print $i 同上面的 while 语句做同样的工作。 for 语句还有一种可选的形式,它适合于访问关联数组的元素: for (i in array) 语句 把 i 依次设置为 array 的每个元素并重复执行后面的语句。元素是按明显的随机次序访问的。如果在循环期间 i 被改变了,或者访问了新元素,就会出现混乱。 在 if、while、for 的条件部分中的表达式可以包括关系算符如 <、<=、>、>=、==(“等于”)、!=(“不等于”);带有匹配算符 ~ 和 !~ 表示匹配的正则表达式;逻辑算符 ||、&& 和 !;当然还有用于组合的圆括号。

break 语句导致从围绕它 while 或 for 中立即退出,continue 语句导致开始下一次重复。

next 语句导致立即跳转到下一个记录并从头开始扫描模式。exit 语句导致程序表现得如同已经到达了输入的结束。

在 awk 程序中可以放置注释: 它们开始于字符 # 并结束于本行的结束处。比如

print x, y # 这是一个注释

4. 设计

UNIX 系统已经提供一些程序,它们通过传递输入经过某种选择机制而进行操作。grep 是最早和最简单的,它只打印匹配一个单一的指定模式的所有行。egrep 提供了更一般的模式,就是说,完全一般性的正则表达式;fgrep 通过特别快的算法查找关键字的集合。

sed 提供了编辑器 ed 的大多数编辑设施,并应用于输入流之上。这些程序都不提供数值功能、逻辑关系或变量。

lex 提供了一般性的正则表达式的识别能力,并充当 C 程序生成器,在能力上是没有限制的。但使用 lex 需要 C 编程的知识,并且 lex 程序必须必须在使用之前编译和装载,所以不鼓励在简短的应用中使用。

awk 尝试填充可能性矩阵中的空白。它提供了一般性的正则表达式能力和隐含的输入/输出循环。它还提供方便的数值处理、变量、更一般性的选择和在动作中的控制流。它不需要编译和 C 语言知识。最后,awk 提供了访问行中字段的方便的方式;在这方面它是唯一的。

awk 还尝试完全整合字符串和数值,通过把所有数量都作为既是字符串又是数处理,尽可能晚的确定哪个表示是合适的。在大多数情况下用户可以简单的忽略这种区别。

开发 awk 的多数努力在于确定 awk 应该做什么与不应该做什么(例如,它不做字符串替换),和应当采用什么语法(没有显式的连接算符),而不是书写和调试代码。我们尝试使语法强力但易于使用并适于扫描文件。例如,缺乏声明和隐含的初始化,尽管对于通用编程语言是个坏主意,但对意图用于甚至是在命令行上合成的小程序的一门语言而言是需要的。

在实践中,awk 的使用适合两个广泛的范畴。其一可以叫做“报表生成”— 处理一个输入,提取计数,总和等。这也包括写琐碎的数据验证程序,比如校验一个字段只包含数值信息或特定分界符是正确配对的。文本和数值处理的组合在这种情况下是没有价值的。

第二个用途是做数据转换器,从一个程序生成的一种形式转换成另一个程序期望的另一种形式。最简单的例子只是选择字段,可能再做些重新安排。
5. 实现

awk 语言的实际实现利用了 UNIX 操作系统上可用的开发工具。文法使用 yacc 规定;词法分析使用 lex;正则表达式识别器是直接从这些表达式构造出来的确定有限自动机。awk 程序被翻译成一个分析树,并接着直接用一个简单的解释器执行它。

awk 是为易于使用而不处理速度而设计;变量类型的延迟评估和分解到字段的需要使在任何情况下都难于达到高速。尽管如此,程序不是慢得不能工作。

下面的表 I 展示了在 PDP-11/70 上 UNIX 程序 wc、grep、egrep、fgrep、sed、lex 和 awk 在下列简单任务上的执行(用户+系统)时间:

* 1. 计数行数。
* 2. 打印包含“doug” 的所有行。
* 3. 打印包含“doug”、 “ken” 或“dmr”的所有行。
* 4. 打印每行的第三个字段。
* 5. 依次打印每行的第三和第二个字段。
* 6. 分别把包含“doug”、“ken”和“dmr”的所有行添加到文件“jdoug”、“jken”和 “jdmr”。
* 7. 打印每行并前导上“行号 :”。
* 8. 总和一个表的第四列。

程序 wc 只计数它输入中的字、行和字符;其他的我们都提到过。在所有情况下,输入都是使用命令 ls −l 建立的包含 10,000 行的文件;每行都有如下形式

-rw-rw-rw- 1 ava 123 Oct 15 17:05 xxx

这个输入的总长度是 452,960 个字符。lex 的时间不包括编译和装载。

如同预期的一样,awk 不如特殊工具 wc、sed 或 grep 家族程序那么快,但是比更一般性的工具 lex 要快。在所有情况下,这些任务表达为 awk 程序同表达为其他语言一样容易;涉及字段的任务相当易于表达为 awk 程序。某些测试程序同时用 awk、sed 和 lex 展示。

任务
程序 1 2 3 4 5 8 7 8
wc 8.6






grep 11.7 13.1





egrep 6.2 11.5 11.6




fgrep 7.7 13.8 16.1




sed 10.2 11.6 15.8 29.0 30.5 16.1

lex 65.1 150.1 144.2 67.3 70.3 104.0 81.7 92.8
awk 15.0 25.6 29.9 33.3 38.9 46.4 71.4 31.1

表 I. 程序的执行时间。(单位是秒)

下面展示完成某些任务的程序。lex 程序一般长得难以展示。

awk:

1. END {print NR}
2. /doug/
3. /ken|doug|dmr/
4. {print $3}
5. {print $3, $2}
6. /ken/ {print >"jken"}
/doug/ {print >"jdoug"}
/dmr/ {print >"jdmr"}
7. {print NR ": " $0}
8. {sum = sum + $4}
END{print sum}

SED:


1. $=
2. /doug/p
3. /doug/p
/doug/d
/ken/p
/ken/d
/dmr/p
/dmr/d
4. /[^ ]* [ ]*[^ ]* [ ]*\([^ ]*\) .*/s//\1/p
5. /[^ ]* [ ]*\([^ ]*\) [ ]*\([^ ]*\) .*/s//\2 \1/p
6. /ken/w jken
/doug/w jdoug
/dmr/w jdmr

LEX:

1. %{
int i;
%}
%%
\n i++;
. ;
%%
yywrap() {
printf("%d\n", i);
}
2. %%
^.*doug.*$ printf("%s\n", yytext);
. ;
\n ;

BASH fork 炸弹 简述

在 bash 中, 有个经典的递归脚本: Fork炸弹, 他是Jaromil 在 2002 年设计的, 一个精简的 fork炸弹的实现,整个程序从函数定义到调用仅仅包含 13 个字符, 好厉害!!!

-----------------------------------------------------------------------

.(){ .|.& };.

-----------------------------------------------------------------------

这串字符乍看上去根本就看不出个所以然来,下面让我们逐一解释一下它究竟在干些什么??

-----------------------------------------------------------------------

1 .()
2 {
3 .|.&
4 }
5 ;
6 .

-----------------------------------------------------------------------
第 1 行说明下面要定义一个函数,函数名为小数点,没有可选参数。
第 2 行表示函数体开始。
第 3 行是函数体真正要做的事情,首先它递归调用本函数,然后利用管道调用一个新进程(它要做的事情也是递归调用本函数),并将其放到后台执行。
第 4 行表示函数体结束。
第 5 行并不会执行什么操作,在命令行中用来分隔两个命令用。从总体来看,它表明这段程序包含两个部分,首先定义了一个函数,然后调用这个函数。
第 6 行表示调用本函数。


一旦运行 fork 炸弹,会以2的指数次幂的速度不断产生新进程,这会导致系统资源会被迅速耗光,最终除非重新启动机器,否则基本上就毫无办法了。为了防止这会造成太大的损害,我们可以使用 ulimit 限制每个用户能够创建的进程数.

Bash的fork bomb以及解决办法

:(){ :|:& };:
上面的代码在CU上看到的,有名的bash fork() bomb。在Bash 里跑这段代码,Linux系统差不多都会死。我在VM里的RHEL5上试着运行后,立即ps看到满屏的bash进程,之后系统就卡住了动不了。没办法,只好强行Reboot。

乍一看这段代码确实不好理解,如果展开来看就清晰多了。

:()
{
:|:&
};
:

还是晕晕的?再换一下就更好理解了。

a()
{
a|a&
};
a

简化一下,先定义一个函数a,再运行a。a函数里面递归调用自身a,并且利用管道fork一个子bash进程在后台运行a。

于是,运行a的后果是当前的bash陷入a的死循环,不断的fork,而且fork出来的子进程又都做同样的事,这样要不了一会儿,栈空间挂了,进程列表也会挂,系统就要崩溃了。

:(){ :|:& };:这个我刚开始也让我困惑,不知道bash里:可以用做函数名。还有:在bash里是builtin,具体可以info :看到其作用。

有必要了解bash解释命令的顺序

  1. Aliases
  2. Keywords such asfunctionand several others, likeifandfor
  3. Functions
  4. Built-ins likecdandtype
  5. Scripts and executable programs, for which the shell searches in the directories listed in thePATH

environment variable bash中函数优先内置命令,于是:被当作函数解释了。

预防 fork bomb的方法就是限制每个用户的进程数,可以在/etc/security/limits.conf里设置。具体用法可以参见该文件的注释部分或者man limits.conf

what happens if the parent terminates before the child?

The answer is that the init process becomes the parent process of any process whose parent terminates. We say that the process has been inherited by init. What normally happens is that whenever a process terminates, the kernel goes through all active processes to see whether the terminating process is the parent of any process that still exists. If so, the parent process ID of the surviving process is changed to be 1 (the process ID of init). This way, we're guaranteed that every process has a parent.

Zombie process


From Wikipedia, the free encyclopedia


On Unix and Unix-like computer operating systems, a zombie process or defunct process is a process that has completed execution but still has an entry in the process table. This entry is still needed to allow the process that started the (now zombie) process to read its exit status. The term zombie process derives from the common definition of zombie—an undead person. In the term's colorful metaphor, the child process has died but has not yet been reaped.

When a process ends, all of the memory and resources associated with it are deallocated so they can be used by other processes. However, the process's entry in the process table remains. The parent can read the child's exit status by executing the wait system call, at which stage the zombie is removed. The wait call may be executed in sequential code, but it is commonly executed in a handler for the SIGCHLD signal, which the parent receives whenever a child has died.

After the zombie is removed, its process ID and entry in the process table can then be reused. However, if a parent fails to call wait, the zombie will be left in the process table. In some situations this may be desirable, for example if the parent creates another child process it ensures that it will not be allocated the same process ID. On modern UNIX-like systems (that comply with SUSv3 specification in this respect), the following special case applies: if the parent explicitly ignores SIGCHLD by setting its handler to SIG_IGN (rather than simply ignoring the signal by default) or has the SA_NOCLDWAIT flag set, all child exit status information will be discarded and no zombie processes will be left.

A zombie process is not the same as an orphan process. An orphan process is a process that is still executing, but whose parent has died. They do not become zombie processes; instead, they are adopted by init (process ID 1), which waits on its children.

Zombies can be identified in the output from the Unix ps command by the presence of a “Z” in the “STAT” column. Zombies that exist for more than a short period of time typically indicate a bug in the parent program, or just an uncommon decision to reap children (see example). As with other leaks, the presence of a few zombies is not worrisome in itself, but may indicate a problem that would grow serious under heavier loads. Since there is no memory allocated to zombie processes except for the process table entry itself, the primary concern with many zombies is not running out of memory, but rather running out of process ID numbers.

To remove zombies from a system, the SIGCHLD signal can be sent to the parent manually, using the kill command. If the parent process still refuses to reap the zombie, the next step would be to remove the parent process. When a process loses its parent, init becomes its new parent. Init periodically executes the wait system call to reap any zombies with init as parent.

[edit] Examples

Synchronously waiting for specific child processes in a (specific) order may leave zombies present longer than the above-mentioned “short period of time”. It is not necessarily a program bug, but rather a programming paradigm that is not seen very often in the wild.

#include 
#include
#include

int main(void)
{
pid_t pids[5];
int i;

for (i = 4; i >= 0; --i) {
pids[i] = fork();
if (pids[i] == 0) {
sleep(i+1);
_exit(0);
}
}

for (i = 4; i >= 0; --i)
waitpid(pids[i], NULL, 0);

return 0;
}

Fvwm简介

Fvwm is a window manager for X11. It is designed to minimize memory consumption, provide a 3D look to window frames, and a virtual desktop.

并不是任何人都会喜欢 FVWM。使用 FVWM 显然不像用 KDE,Gnome 的桌面那么简单,你需要自己对它进行配置。它是一个老牌的,长久不衰的窗口管理器,它永远以一个忠实的 Xwindow 窗口管理器的方式工作。使用 FVWM,你可以学到很多有关 Xwindow 的东西,你会很快的明白 Xwindow 的工作原理,见识到 Xwindow 的强大和灵活。

如果你喜欢随意的控制自己窗口,让它们都乖乖听话,而不是老是跳出来挡在你面前。你喜欢随意定制自己窗口样式,喜欢快速高效的控制窗口,喜欢节省资源,…… 总之,你是一个挑剔的人。那么 FVWM 就是你最终的选择。

看看牛人的fvwm:http://www.fvwm.org/screenshots/desktops/

相关学习资料:

王垠的主页中的fvwm相关的网页:http://docs.huihoo.com/homepage/shredderyin/fvwm_frame.html

官网:http://www.fvwm.org/

英文版(fvwm入门指南):http://www.zensites.net/fvwm/guide/

中文版fvwm入门指南:http://blog.chinaunix.net/u1/37261/showart_293678.html

这个指南里有一个很好的开始的配置文件和它要用到的图片资源.
这是效果图:


还有一个网页不错:http://xueruini.myipcn.org/publish/GNU/fvwm.html

最后说一个重点的资源:fvwm的man page(中文的)

http://blog.chinaunix.net/u1/34190/showart.php?id=263888

How X over SSH really works






Imagine you are sitting in front of a machine named "home" that has a keyboard, mouse, display, and is running an X server. Now you open a terminal and ssh to a machine called "remote"
(which doesn't need to have an X server running), and run a program
like "firefox" which pops a window in your screen. How does this all
work?

First, let's clear up the client/server terminology confusion. When talking about X:
  • X client: a process (like firefox or xemacs) which uses the X client API to display things and receive mouse/keyboard events.
  • X server: a process (usually just "X") which X clients connect to. At times (as we'll see below) other processes can act as X servers.
Whenever an X client starts up, it reads the local $DISPLAY environment variable, whose value looks like: [hostname]:display_number[.screen_number]. The X client immediately opens a connection to that X server. If it can't, it fails:

user@home: echo $DISPLAY
:0 # hostname is "localhost" by default
user
@home: xcalc # pops up a calculator on my screen
user@home: DISPLAY="nosuchhost:99"
user@home: xcalc
Error: Can't open display: nosuchhost:99

Now let's see what happens when you ssh to another machine:

user@home: ps aux | grep X # yep, X server running @home
root ... /usr/bin/X :0 ...
user@home: ssh -X user@remote # -X enables X-forwarding
user@remote: ps aux | grep X # nope, no X server here
user@remote: echo $DISPLAY
:11.0
user@remote: xcalc # pops up screen @home

Wait a minute, the $DISPLAY variable is pointing to the localhost ("remote"). Natural questions to ask at this point:
  • There is no X server @remote, so why didn't xcalc just fail on startup?
  • Why was the display number "11".
  • How did xcalc show something @home?
The answer has to do with the ssh-daemon running @remote:

user@remote: ps aux | grep user
root ... sshd:user@pts/11

What's happening is that there's an "X emulator" running @remote that was setup just for your ssh session, that is listening on display 11.

To review, here's a play-by-play:
  1. You type "ssh -X user@remote" in your terminal
  2. The ssh process connects to the sshd server @remote.
  3. sshd spawns a new process that is an X-server-emulator listening on some display number, e.g. "11"
  4. sshd sets the $DISPLAY to point to that local "X-server" (e.g. ":11")
  5. xcalc reads this $DISPLAY and conncects to this X-server. xcalc thinks it's displaying to the local machine.
  6. the X-server-emulator simply forwards the X commands from xcalc through the ssh connection, to the original ssh process.
  7. The ssh process @home now acts as a normal X-client and sends those commands to the X-server @home.
Some of you might be wondering: wasn't the X protocol designed to go over the network? Can't you do all this without ssh? You might be tempted to try something like:
user@remote: DISPLAY="home:0"
user@remote: xcalc

This doesn't work because the X server @home won't let other hosts connect to it. To change this (not that you should -- see below) you can do:

user@home: xhost +remote

xhost
is a command which says "that host can connect to our X-server".
However, everybody uses ssh X forwarding instead. Here are some security reasons why:
  • Normally, X-traffic (like your keystrokes) is sent unencrypted from X-client to X-server.
  • Ssh nicely sends that data through an encrypted channel, so it doesn't go over the internet in the clear.
  • "xhost +remote" is putting a lot of trust in 'remote' being a nice guy. If remote ever gets hacked, it could connect to the X-server @home and listen to all its keystrokes.
There's also an issue with firewalls: by doing "DISPLAY=home:0", you're assuming that a connection can be established from remote -> home. But this isn't always possible -- home might be sitting behind a firewall (like your Netgear router). Since the ssh-connection was setup from home-> remote, it takes advantage of this already-established connection.

Other notes for the curious:
- if $DISPLAY is set to "localhost:0" (or any explicitly named host) it uses tcp-ip to send the X-traffic locally.
- if $DISPLAY is just ":0" it uses a special (more efficient, non-tcp-ip) connection.

防止ssh暴力破解软件 denyhosts[转]

防止ssh暴力破解软件 denyhosts
无聊中查看了一下/var/log/secure日志,一看吓了一大跳。
Mar 31 15:21:32 rhel4 sshd[6057]: Failed password for invalid user kevin from ::ffff:211.192.211.98 port 64296 ssh2
Mar 31 15:21:33 rhel4 sshd[6059]: Invalid user kev from ::ffff:211.192.211.98
Mar 31 15:21:35 rhel4 sshd[6059]: Failed password for invalid user kev from ::ffff:211.192.211.98 port 64643 ssh2
Mar 31 15:21:37 rhel4 sshd[6061]: Invalid user kev from ::ffff:211.192.211.98
Mar 31 15:21:39 rhel4 sshd[6061]: Failed password for invalid user kev from ::ffff:211.192.211.98 port 64992 ssh2
Mar 31 15:21:40 rhel4 sshd[6063]: Invalid user hector from ::ffff:211.192.211.98
Mar 31 15:21:43 rhel4 sshd[6063]: Failed password for invalid user hector from ::ffff:211.192.211.98 port 1351 ssh2
Mar 31 15:21:44 rhel4 sshd[6065]: Invalid user harold from ::ffff:211.192.211.98
Mar 31 15:21:46 rhel4 sshd[6065]: Failed password for invalid user harold from ::ffff:211.192.211.98 port 1695 ssh2
Mar 31 15:21:48 rhel4 sshd[6067]: Invalid user homer from ::ffff:211.192.211.98
Mar 31 15:21:50 rhel4 sshd[6067]: Failed password for invalid user homer from ::ffff:211.192.211.98 port 2048 ssh2
Mar 31 15:21:51 rhel4 sshd[6069]: Invalid user simpson from ::ffff:211.192.211.98
Mar 31 15:21:54 rhel4 sshd[6069]: Failed password for invalid user simpson from ::ffff:211.192.211.98 port 2399 ssh2
Mar 31 15:21:55 rhel4 sshd[6071]: Invalid user helena from ::ffff:211.192.211.98
Mar 31 15:21:57 rhel4 sshd[6071]: Failed password for invalid user helena from ::ffff:211.192.211.98 port 2737 ssh2
Mar 31 15:21:59 rhel4 sshd[6073]: Invalid user selena from ::ffff:211.192.211.98
Mar 31 15:22:01 rhel4 sshd[6073]: Failed password for invalid user selena from ::ffff:211.192.211.98 port 3078 ssh2
Mar 31 15:22:02 rhel4 sshd[6075]: Invalid user helen from ::ffff:211.192.211.98
Mar 31 15:22:10 rhel4 sshd[6075]: Failed password for invalid user helen from ::ffff:211.192.211.98 port 3422 ssh2
Mar 31 15:22:11 rhel4 sshd[6077]: Invalid user helene from ::ffff:211.192.211.98
Mar 31 15:22:13 rhel4 sshd[6077]: Failed password for invalid user helene from ::ffff:211.192.211.98 port 4234 ssh2
Mar 31 15:22:15 rhel4 sshd[6079]: Invalid user gina from ::ffff:211.192.211.98
Mar 31 15:22:17 rhel4 sshd[6079]: Failed password for invalid user gina from ::ffff:211.192.211.98 port 4577 ssh2
Mar 31 15:22:18 rhel4 sshd[6081]: Invalid user francisc from ::ffff:211.192.211.98
Mar 31 15:22:21 rhel4 sshd[6081]: Failed password for invalid user francisc from ::ffff:211.192.211.98 port 4915 ssh2
Mar 31 15:22:22 rhel4 sshd[6083]: Invalid user fred from ::ffff:211.192.211.98
Mar 31 15:22:24 rhel4 sshd[6083]: Failed password for invalid user fred from ::ffff:211.192.211.98 port 5245 ssh2
Mar 31 15:22:26 rhel4 sshd[6087]: Invalid user frederic from ::ffff:211.192.211.98
Mar 31 15:22:28 rhel4 sshd[6087]: Failed password for invalid user frederic from ::ffff:211.192.211.98 port 5593 ssh2
Mar 31 15:22:29 rhel4 sshd[6090]: Invalid user felix from ::ffff:211.192.211.98
Mar 31 15:22:32 rhel4 sshd[6090]: Failed password for invalid user felix from ::ffff:211.192.211.98 port 5933 ssh2
Mar 31 15:22:33 rhel4 sshd[6092]: Invalid user filip from ::ffff:211.192.211.98
Mar 31 15:22:35 rhel4 sshd[6092]: Failed password for invalid user filip from ::ffff:211.192.211.98 port 6271 ssh2
Mar 31 15:22:37 rhel4 sshd[6094]: Invalid user philipe from ::ffff:211.192.211.98
Mar 31 15:22:39 rhel4 sshd[6094]: Failed password for invalid user philipe from ::ffff:211.192.211.98 port 6619 ssh2
Mar 31 15:22:40 rhel4 sshd[6096]: Invalid user bruce from ::ffff:211.192.211.98
Mar 31 15:22:43 rhel4 sshd[6096]: Failed password for invalid user bruce from ::ffff:211.192.211.98 port 6972 ssh2
Mar 31 15:22:44 rhel4 sshd[6098]: Invalid user ernest from ::ffff:211.192.211.98
Mar 31 15:22:46 rhel4 sshd[6098]: Failed password for invalid user ernest from ::ffff:211.192.211.98 port 7305 ssh2
Mar 31 15:22:48 rhel4 sshd[6100]: Invalid user luiza from ::ffff:211.192.211.98
Mar 31 15:22:50 rhel4 sshd[6100]: Failed password for invalid user luiza from ::ffff:211.192.211.98 port 7651 ssh2
Mar 31 15:22:51 rhel4 sshd[6102]: Invalid user edouard from ::ffff:211.192.211.98
好多类似上面的攻击,可以看到用户在一个一个测试用户名和密码,汗!!!
立即处理该问题,用GOOGLE搜索了一下,找到一个软件denyhosts。
先从网络上下载该软件,我下载的是denyhosts-2.6.tar.gz
解压缩,进入源目录,直接安装
enyHosts是用Python2.3写的一个程序,所以安装起来和普通LINUX安装文件有所不同
1首选检查Sshd是否支持Tcpwrap,只有支持Tcpwrap才可以安装Denyhost
ldd /usr/sbin/sshd |grep wrap
2需要检查Python的版本,Python2.3以上版本可以直接安装 python –V
我安装的RHEL4.0,这里都OK了
3进入解压缩后的目录,执行安装python setup.py install
程序脚本自动安装到/usr/share/denyhosts
库文件自动安装到/usr/lib/python2.3/site- packages/DenyHosts
denyhosts.py自动安装到/usr/bin
4 cd /usr/share/denyhosts/拷贝模板文件
5 cp daemon-control-dist daemon-control设置好启动脚本的所属用户和权限
6 chown root daemon-control
7 chmod 700 daemon-control生成Denyhost的主配置文件,(将模板文件中开头是#的过滤后再导入到Denyhost.cfg)
8 grep -v "^#" denyhosts.cfg-dist > denyhosts.cfg
编辑Denyhost.cfg文件
9 vi denyhosts.cfg
----------------denyhosts.cfg------------------------
SECURE_LOG = /var/log/secure
#RedHat/Fedora Core分析该日志文件
#其它版本linux根据denyhosts.cfg-dist内提示选择。PURGE_DENY = 30m
#过多久后清除
DENY_THRESHOLD_INVALID = 1
#允许无效用户(/etc/passwd未列出)登录失败的次数DENY_THRESHOLD_VALID = 5
#允许有效(普通)用户登录失败的次数DENY_THRESHOLD_ROOT = 3
#允许root登录失败的次数
HOSTNAME_LOOKUP=NO
#是否做域名反解
----------------denyhosts.cfg------------------------

将Denyhost启动脚本添加到自动启动中
10 echo '/usr/share/denyhosts/daemon-control start'>>/etc/rc.d/rc.local

启动Denyhost的进程
11 /usr/share/denyhosts/daemon-control start

可以查看到Denyhost在运行中
12 ps -ef |grep deny

在另外一台机器上使用Ssh进行连接,当在连续几次输入错误的密码后,会被自动阻止掉,在一定时内不可以再连接

Ssh连接记录的日志文件
13 tail /var/log/secure –f
本地实例
Mar 31 20:21:48 rhel4 sshd[11225]: Failed password for root from ::ffff:114.245.149.223 port 2039 ssh2
Mar 31 20:21:54 rhel4 sshd[11225]: Accepted password for root from ::ffff:114.245.149.223 port 2039 ssh2
Mar 31 22:21:46 rhel4 sshd[14205]: Failed password for root from ::ffff:173.45.67.210 port 42075 ssh2
Mar 31 22:21:51 rhel4 sshd[14211]: Failed password for root from ::ffff:173.45.67.210 port 42422 ssh2
Mar 31 22:21:56 rhel4 sshd[14216]: Failed password for root from ::ffff:173.45.67.210 port 42749 ssh2
Mar 31 22:22:01 rhel4 sshd[14222]: Failed password for root from ::ffff:173.45.67.210 port 43100 ssh2
Mar 31 22:22:05 rhel4 sshd[14224]: Failed password for root from ::ffff:173.45.67.210 port 43454 ssh2
Mar 31 22:22:20 rhel4 sshd[14230]: Failed password for root from ::ffff:173.45.67.210 port 43768 ssh2
Apr 1 09:15:28 rhel4 sshd[30696]: Accepted password for root from ::ffff:211.155.190.247 port 52048 ssh2
Denyhost日志文件
14 tail /var/log/denyhosts –f
[root@rhel4 ~]# tail /var/log/denyhosts -f
2009-04-01 09:27:48,571 - denyfileutil: INFO num entries purged: 0
2009-04-01 10:19:18,106 - denyhosts : INFO /var/log/secure has been rotated
2009-04-01 10:19:20,170 - denyhosts : INFO new denied hosts: ['173.45.67.210', '61.191.53.99', '211.155.190.247', '63.216.183.4', '211.80.157.210', '204.110.14.16', '121.174.8.16', '221.221.255.121', '60.195.250.54', '211.192.211.98', '222.218.156.41', '222.87.0.97', '219.153.66.71']
2009-04-01 10:27:50,097 - denyfileutil: INFO purging entries older than: Wed Apr 1 09:57:50 2009
2009-04-01 10:27:50,099 - denyfileutil: INFO num entries purged: 0
2009-04-01 11:27:49,562 - denyfileutil: INFO purging entries older than: Wed Apr 1 10:57:49 2009
2009-04-01 11:27:49,564 - loginattempt: INFO purging_hosts: ['173.45.67.210', '61.191.53.99', '211.155.190.247', '63.216.183.4', '211.80.157.210', '204.110.14.16', '121.174.8.16', '221.221.255.121', '60.195.250.54', '211.192.211.98', '222.218.156.41', '222.87.0.97', '219.153.66.71']
2009-04-01 11:27:49,565 - denyfileutil: INFO num entries purged: 13
2009-04-01 12:27:49,033 - denyfileutil: INFO purging entries older than: Wed Apr 1 11:57:49 2009
2009-04-01 12:27:49,034 - denyfileutil: INFO num entries purged: 0

Denyhost将恶意连接的IP记录到Hosts.deny文件中,过一定时间后再从该文件中清除(Denyhost.cfg中设定的时间)
15 vi /etc/hosts.deny
# DenyHosts: Tue Mar 31 16:27:57 2009 | sshd: 173.45.67.210
sshd: 173.45.67.210
# DenyHosts: Tue Mar 31 16:27:57 2009 | sshd: 61.191.53.99
sshd: 61.191.53.99
# DenyHosts: Tue Mar 31 16:27:57 2009 | sshd: 63.216.183.4
sshd: 63.216.183.4
# DenyHosts: Tue Mar 31 16:27:57 2009 | sshd: 211.80.157.210
sshd: 211.80.157.210
# DenyHosts: Tue Mar 31 16:27:57 2009 | sshd: 204.110.14.16
sshd: 204.110.14.16
# DenyHosts: Tue Mar 31 16:27:57 2009 | sshd: 121.174.8.16
sshd: 121.174.8.16

10 Expert Ubuntu Tricks[转]

Recently I started work on a new Ubuntu tips book that will partner my existing title, Ubuntu Kung Fu. The new book is still being planned and won't be published until next year, but I thought I'd share 10 tips that are on my list to be included. If you have any others that you think would go into such a book, put them in the comments below. I'd love to hear them, as would other readers, I'm sure.

These tips aren't Ubuntu-specific, but they've been tested on Ubuntu, and I can't guarantee they'll work on other distros. You might already know about some or all of them them, but resist the temptation to gloat about this in the comments. You're just extra clever, OK?

With that said, let's start!
1. Open a Superuser Run Programs Dialog

You probably already know that hitting Alt+F2 will cause a "Run Programs" dialog box to appear. Here you can type any program name to run it -- I often use it to run gconf-editor, which hasn't got a menu entry, or example. However, if you type gksu into a terminal window (with nothing following), a similar dialog box appears, but this time it will let you run the program as root (or any other user on the system). You can bind the gksu command to a keyboard shortcut (perhaps Shift+Alt+F2) using System, Preferences, Keyboard Shortcuts, to effectively produce a "superuser" Run Programs dialog.
2. Install Packages Quickly With GDebi

I spent a long time ignoring the GDebi program. To remind you, this is a GUI application that allows the installation of packages you've manually downloaded. It attempts to resolve dependencies using the repositories, which is a very useful feature. However, I've always preferred the good old-fashioned dpkg command. Then one day I tried GDebi at the command line and was shocked to find it also runs in a fuss-free non-GUI mode (i.e. sudo gdebi package.deb), yet still has the ability to resolve dependencies. Give it a try. Once you do, you may never want to use dpkg -i again.
3. CD Tricks

I'm sure that even bash experts occasionally slap themselves on the forehead and say, "Wow! I never knew you could do that!". Recently I learned two tricks for the cd (change directory) command that had passed me by until now. Typing cd on its own will switch you back to your /home directory (i.e. the equivalent of cd ~). Typing cd - will switch you to the last directory you were browsing before you switched to the current one.
4. Add Directories To the Directory Stack With PUSHD

While we're on the subject of directories, let's talk about the directory stack. Quite simply, this is a list of directories stored by bash. The currently-browsed directory always tops the list, but the list is otherwise empty until you add a new directory, which you can do using the pushd command. For example, pushd /usr/bin will add /usr/bin. It will also switch you to that directory, so you could use it instead of cd to navigate (the -n command option will let you add a directory but stay where you are). The dirs command will show the directory list (remember that the currently-browsed directory will always be at the top). popd deletes the topmost entry in the list, and switches you to the next in the list. Give the directory list a try. It can be very useful if you're administering a system and have to leap from directory to directory, and are inclined to forget where important things are.
5. Kill Processes Quickly With PKILL

To kill a process I've always either used top, or the kill or killall commands along with ps|aux to discover process numbers/names. However, the pkill command removes a lot of work -- pkill firefox, for example, will search the list of processes for anything matching firefox, and then kill it (i.e. send a SIGTERM). pstree is also a pretty cool command, and will show all the processes in a family-tree arrangement, organized by who owns them.
6. Customize Gnome With Gnome Control Center

For those who have trouble giving up their Windows cravings, and who want a nice organized Control Panel-like experience, consider using gnome-control-center for your system configuration needs. Adding a desktop shortcut to this program can help newbies get to grips with Ubuntu, giving them a familiar Windows-like experience, and avoid forcing them to explore the scary System menu.
7. Launch OpenOffice.org Faster

If you use OpenOffice.org a lot, you might be frustrated at how long it takes to start each time. To get around this, open the Sessions program (called Startup Manager in Jaunty; whatever the case, click System, Preferences, Startup Applications to find it) and add a new entry. In the Command field, type openoffice -nodefault -nologo. Then reboot. This will cause OpenOffice.org to be cached when the Gnome desktop starts up, so starting any OO.org application in the future will happen in a split second. Effectively, you're moving the OpenOffice.org startup delay to initial boot-up, but you'll hardly notice it.
8. Clear Up Disk Clutter In a Jiffy

Running short of disk space? Try typing sudo apt-get autoremove and then sudo apt-get clean into a terminal window. The first command removes any unused (redundant) dependencies from the system. The second removes all cached package files. Both are harmless. On a well-used system that's been updated a couple of times, you could free-up as much as a gigabyte using these methods. (Compare before and after using the df -h command.)
9. Figure Out Missing File Extensions

Been sent a file without an extension by e-mail? No idea what type of file it is? (Mac users are particularly guilty of the sin of considering file extensions optional.) Try the file command. Just specify the filename straight afterwards. Also, give the strings command a try. This will show any "printable strings" within a binary file (i.e. anything that isn't unprintable, which usually indicates data). The type of file is usually listed right at the top, so it's a good idea to pipe the output of strings into head (i.e. strings filename|head).
10. Don't Forget Your Man Pages

Check out these interesting but not-widely-read man pages: intro -- a beginner's guide to the command-line; hier -- a rundown of the filesystem hierarchy; builtins -- mini man pages for miscellaneous commands that don't have man pages of their own (including pushd, popd and dirs, as discussed above).

Configure RXVT


  • The default rxvt font size is too small. How do I enlarge it?
    • Open C:\MSYS\1.0\msys.bat with a text editor and search for a line containing "80x25". Then replace it with:
       rem The following should be all one line.
      start rxvt -backspacekey ^H -sl 2500 -fg grey90 -bg black -sr -fn "Courier-bold-20"
      -tn msys -geometry 80x25 -e /bin/sh --login -i
    • You can change the Courier font above with your favorite one. Note that using TrueType fonts (such as Courier New or Lucida Console) will result in sluggish performance under Windows XP.
  • Why don't the Home and End keys work in rxvt and vim?
    • This is because rxvt's terminal emulation uses different escape codes for these two keys. This sample ~/.inputrc file solves this issue:
            set completion-query-items 100
      set completion-ignore-case on
      set show-all-if-ambiguous off

      set input-meta on
      set output-meta on
      set convert-meta off
      set bell-style none

      "\e[2~": paste-from-clipboard
      "\e[3~": delete-char
      "\e[5~": beginning-of-history
      "\e[6~": end-of-history
      "\e[7~": beginning-of-line
      "\e[8~": end-of-line
    • Also, you need to set up your ~/.vimrc to enable the Home/End keys in ViM:
            set nocompatible
      set backspace=2
      syntax on

      map [7~
      map [8~

      imap [7~
      imap [8~

让msys的shell支持中文输入输出



~/.inputrc
set completion-query-items 100
set completion-ignore-case on
set show-all-if-ambiguous off

set input-meta on
set output-meta on
set convert-meta off
set bell-style none

"\e[2~": paste-from-clipboard
"\e[3~": delete-char
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[7~": beginning-of-line
"\e[8~": end-of-line


ls --show-control-chars



判断当前bash是否为login shell

echo "$0"
如果显示`-bash'则说明是login shell
如果显示`bash'则说明不是login shell

how to determine if the current shell is a login shell?

cygwin中文乱码

msys中文显示


注意:中文注释可以保留,但文件必须采用linux文件格式,即用\n作换行符。可以用notepad++, vim等工具创建

.bash_profile

# 让ls和dir命令显示中文和颜色
alias ls='ls --show-control-chars --color'
alias dir='dir -N --color'
alias less='less -r'
# 设置为中文环境,使提示成为中文
export LANG="zh_CN.GBK"
# 输出为中文编码
export OUTPUT_CHARSET="GBK"

.inputrc

# 关闭bash命令行8字节字符转义符的转换
set convert-meta off

# 使bash命令行支持8字节字符输入
set input-meta on

# 使bash命令行支持8字节字符输出
set output-meta on

set meta-flag on

set completion-ignore-case on


Why don't international (Unicode) characters work?

Internationalization is a complex issue. The short answer is that Cygwin is not Unicode-aware, so things that might work in Linux will not necessarily work on Cygwin. However, some things do work. To type international characters (£äö) in bash, add the following lines to your ~/.inputrc file and restart bash:

set meta-flag on
set convert-meta off
set output-meta on
set input-meta on
set kanji-code sjis

These are options to the readline library, which you can read about in the bash(1) and readline(3) man pages. Other tools that do not use readline for display, such as less and ls, require additional settings, which could be put in your ~/.bashrc:

alias less='/bin/less -r'
alias ls='/bin/ls -F --color=tty --show-control-chars'
export LANG="ja_JP.SJIS"
export OUTPUT_CHARSET="sjis"

These examples use the Japanese Shift-JIS character set, obviously you will want to change them for your own locale.




mingw,cygwin,gnuwin32

* MinGW:Minimalist GNU for Windows
o 安装MinGW
+ 无配置
o 安装MSYS及MSYSDTK
+ 编辑了/MSYS.bat
1. 加入chdir,使可以在目录外运行。
2. 通过命令行参数%~dp0得到MSYS的路径。
3. 删除其他命令行参数相关的动作。
4. 将命令行参数%~dp1设置为环境变量MSYSINITDIR以备Shell初始目录之用。
5. 将默认的Shell从rxvt改为sh。
+ 增加了/LoadMSYS.bat及/LoadMSYS.reg
1. 作用:扩展命令行参数为完全路径名,将参数传送给MSYS.BAT。
2. 将LoadMSYS.bat放在系统PATH下面,使在任何目录下都可以调用。
3. 编辑注册表ROOT下面的*项和Folder项,以支持鼠标右健直接调用。
4. 导出注册表项为LoadMSYS.reg,以备用。
+ 编辑了/etc/fstab
1. 设置MinGW目录的Mount Point为/mingw
2. 设置MINGW/INFO的Mount Point为/info
3. 创建COMMAND目录,将Mount Point设为/usr/local/bin,以存放用MinGW Gcc编译的程序。
4. 设置了其他一些常用目录的Mount Point。
+ 编辑了/etc/profile
1. export PATH:加入/Mingw/bin。
2. export INFOPATH:目录用;号隔开,作info搜索之用。
3. 如果$MSYSINITDIR不为空,则改变为初始目录(CD之)。
+ 编辑了$HOME/.vimrc
1. 配置复制自win32版的gvim。
2. 加入syntax on:语法高亮。
3. 加入set nu:显示行号。
4. 加入set guifont:设置字体(console版本无效)
o 总结
+ MinGW:许多unix源码,很难在不修改的情况下直接编译
+ MinGW:作为windows native programe(不依赖emulation layer),可以胜任
+ MSYS:对宽字符的支持较差
+ FREEWARE
* Cygwin:GNU+Cygnus+Windows
o 下载时只选择必需的程序包
o 与MSYS近似的许多配置
o 编辑了/etc/bash.bashrc
+ export PATH
+ export INFOPATH
# 与MinGW不同,目录间用:号隔开
+ export MANPATH
o 设置常用目录的Mount Point
+ Cygwin无/etc/fstab文件,Mount Point通过命令行mount命令设置,设置在下次重启之后仍有效。
o 编译了新版本的Gcc及Gdb
o 编译了新版本的make
o 编译了termcap
o 编译了less
o 总结
+ 大多数unix源码都可以顺利编译
+ 对宽字符集支持较好
+ 编译的程序大多数依赖CygDLL
+ 非常丰富的程序库
+ FREEWARE
* GnuWin32:Win32 ports of tools with a GNU or similar open source license
o termcap
+ 在MSYS/MinGW环境下编译成功
o less
+ 需要termcap
+ 在MSYS/MinGw环境下无法编译
# 提示找不到langinfo.h
# 下载了libgw32c的lib版,修改makefile,main.c,filename.c之后,编译成功,但运行时出现错误。
+ 在Cygwin环境下编译成功
+ 用VC97编译成功
o libgw32c
+ 在MSYS/MinGw环境下无法编译
# 错误极多
+ 在Cygwin环境下无法编译
# 错误极多
+ 连接bin版某些程序可以编译
# 运行时出现错误
1. 以编译less为例
o wget
+ 用VC97编译成功
o 总结
+ 源代码大多在MSYS/MinGW下无法成功编译
+ 源代码对Microsoft VC友好
+ 源代码对Cygwin/MinGW友好
+ 作为独立的工具程式较有价值
+ FREEWARE