分类目录归档:Linux

运行shell脚本报错bad interpreter:No such file or directory的解决

最近比较郁闷,写了个自动备份的脚本,在Ubuntu minimal下面运行总是报 … 继续阅读

发表在 Linux | 标签为 , , | 留下评论

Curl模仿http浏览器常见命令

1.获得一个页面

curl http://blog.it580.com
就可以获得http://blog.it580.com的首页。

curl -I http://blog.it580.com
就只获得首页的头信息(HEAD)。

2.表单处理

2.1 GET
例子:

 

curl “http://bbs.it580.com/junk.cgi?birthyear=1905&press=OK”
GET方式,我们提交页面的时候,其实看到的也是这样的一个链接。

2.2 POST
例子:

type=text name=”birthyear”>

curl -d “birthyear=1905&press=%20OK%20″ www.hotmail.com/when/junk.cgi
使用参数 -d,“”内的内容,就是表单的输入部分的名称=你想要输入的值(隐藏的参数也是一样),最后记得加上提交按钮的名称=按钮上的名称。

需要注意的是,POST提交文件的时候,方法是不同的.
例如:

 

curl -F upload=@localfilename -F press=OK [URL]
这里使用的是参数 -F ,而不是 -d.需要特别注意.

3.认证

比如某些网站需要使用认证.可以使用如下命令.比如论坛什么的.

curl -u name:password www.secrets.com

4.模拟指定浏览器

有些变态的站点,限制了使用浏览器的类型.一样难不倒curl.

curl -A “Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)” [URL]
这个就是一个模拟,win2k的ie5.0的一个访问.

5.Cookies

大部分网站都使用cookies,来记录浏览中的信息,识别用户等.自然使用curl也是可以做到的.
比如保存cookies.
curl -D head_cookies http://bbs.it580.com
这样将保存bbs.it580.com的cookies到运行命令的目录下,并命名为head_cookies.

保存了自然要下次使用的.如何使用呢?
curl -b head_cookies http://bbs.it580.com

6.使用代理

很多站点限制了访问的ip,或者说投票的时候发现只能一票一投。就要使用到这个了。
curl -x proxy.test.org:80 http://bbs.it580.com
这样就使用proxy.text.org代理,来访问http://bbs.it580.com了。

继续阅读

发表在 Linux | 留下评论

pogoplug V4 bootlog

PEX 0: PCI Express Root Complex Interface
PEX interface detected Link X1
Net:   egiga0 [PRIME]
Hit any key to stop autoboot:  0

Loading from NAND 128MB 3,3V 8-bit, offset 0x200000
   Image Name:   Linux-2.6.31.8
   Created:      2011-09-28  19:09:20 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2080956 Bytes =  2 MB
   Load Address: 00008000
   Entry Point:  00008000
## Booting image at 00800000 …
   Image Name:   Linux-2.6.31.8
   Created:      2011-09-28  19:09:20 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2080956 Bytes =  2 MB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum … OK
OK

Starting kernel …

Uncompressing Linux……………………………………………………………………………………………………………………. done, booting the kernel.
[    0.000000] Linux version 2.6.31.8 (afenn@kt) (gcc version 4.3.2 (sdk3.3-ct-ng-1.4.1) ) #5 Wed Sep 28 12:09:12 PDT 2011
[    0.000000] CPU: Feroceon 88FR131 [56251311] revision 1 (ARMv5TE), cr=00053977
[    0.000000] CPU: VIVT data cache, VIVT instruction cache
[    0.000000] Machine: Feroceon-KW
[    0.000000] Using UBoot passing parameters structure
[    0.000000] Ignoring unrecognised tag 0x41004345
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] Built 1 zonelists in Zone order, mobility grouping off.  Total pages: 32512
[    0.000000] Kernel command line: console=ttyS0,115200 root=ubi0:rootfs ubi.mtd=4,2048 rootfstype=ubifs
[    0.000000] PID hash table entries: 512 (order: 9, 2048 bytes)
[    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Memory: 128MB = 128MB total
[    0.000000] Memory: 118356KB available (3852K code, 261K data, 124K init, 0K highmem)
[    0.000000] Hierarchical RCU implementation.
[    0.000000] NR_IRQS:128
[    0.000000] Console: colour dummy device 80×30
[    0.000000] Calibrating delay loop… 799.53 BogoMIPS (lpj=3997696)
[    0.230000] Mount-cache hash table entries: 512
[    0.230000] CPU: Testing write buffer coherency: ok
[    0.230000] NET: Registered protocol family 16
[    0.230000] Feroceon L2: Enabling L2
[    0.230000] Feroceon L2: Cache support initialised.
[    0.230000]
[    0.230000] CPU Interface
[    0.230000] ————-
[    0.230000] SDRAM_CS0 ….base 00000000, size 128MB
[    0.230000] SDRAM_CS1 ….disable
[    0.230000] SDRAM_CS2 ….disable
[    0.230000] SDRAM_CS3 ….disable
[    0.230000] PEX0_MEM ….base e0000000, size 128MB
[    0.230000] PEX0_IO ….base f2000000, size   1MB
[    0.230000] PEX1_MEM ….no such
[    0.230000] PEX1_IO ….no such
[    0.230000] INTER_REGS ….base f1000000, size   1MB
[    0.230000] NFLASH_CS ….base fa000000, size   2MB
[    0.230000] SPI_CS ….base f4000000, size  16MB
[    0.230000] BOOT_ROM_CS ….no such
[    0.230000] DEV_BOOTCS ….no such
[    0.230000] CRYPT_ENG ….base f0000000, size   2MB
[    0.230000]
[    0.230000]   Marvell Development Board (LSP Version KW_LSP_5.1.3_patch18)– RD-88F6192A-NAS  Soc: 88F6192 A1 LE
[    0.230000]
[    0.230000]  Detected Tclk 166666667 and SysClk 200000000
[    0.230000] Marvell USB EHCI Host controller #0: c403e740
[    0.730000] PEX0 interface detected Link X1
[    0.740000] pci 0000:00:01.0: PME# supported from D0 D1 D3hot
[    0.740000] pci 0000:00:01.0: PME# disabled
[    0.740000] PCI: bus0: Fast back to back transfers disabled
[    0.740000] mvPexLocalBusNumSet: ERR. Invalid PEX interface 1
[    0.750000] bio: create slab  at 0
[    0.750000] SCSI subsystem initialized
[    0.750000] usbcore: registered new interface driver usbfs
[    0.750000] usbcore: registered new interface driver hub
[    0.750000] usbcore: registered new device driver usb
[    0.750000] NET: Registered protocol family 2
[    0.750000] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.750000] TCP established hash table entries: 4096 (order: 3, 32768 bytes)
[    0.750000] TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
[    0.750000] TCP: Hash tables configured (established 4096 bind 4096)
[    0.750000] TCP reno registered
[    0.750000] NET: Registered protocol family 1
[    0.750000] cpufreq: Init kirkwood cpufreq driver
[    0.760000] XOR registered 4 channels
[    0.760000] XOR 2nd invalidate WA enabled
[    0.760000] cesadev_init(c000d7fc)
[    0.760000] mvCesaInit: sessions=640, queue=64, pSram=f0000000
[    0.760000] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.770000] msgmni has been set to 231
[    0.770000] alg: No test for cipher_null (cipher_null-generic)
[    0.770000] alg: No test for ecb(cipher_null) (ecb-cipher_null)
[    0.770000] alg: No test for digest_null (digest_null-generic)
[    0.770000] alg: No test for compress_null (compress_null-generic)
[    0.780000] alg: No test for stdrng (krng)
[    0.780000] alg: No test for hmac(digest_null) (hmac(digest_null-generic))
[    0.790000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
[    0.790000] io scheduler noop registered
[    0.790000] io scheduler anticipatory registered (default)
[    0.790000] Initializing ths8200_init
[    0.790000] Initializing dove_adi9889_init
[    0.810000] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.810000] serial8250.0: ttyS0 at MMIO 0xf1012000 (irq = 33) is a 16550A
[    0.810000] console [ttyS0] enabled
[    0.820000] Integrated Sata device found
[    0.830000] IRQ 21/mvSata: IRQF_DISABLED is not guaranteed on shared IRQs
[    0.850000] scsi0 : Marvell SCSI to SATA adapter
[    0.860000] scsi1 : Marvell SCSI to SATA adapter
[    0.870000] Loading Marvell Ethernet Driver:
[    0.870000]   o Cached descriptors in DRAM
[    0.880000]   o DRAM SW cache-coherency
[    0.880000]   o 1 Giga ports supported
[    0.880000]   o Single RX Queue support – ETH_DEF_RXQ=0
[    0.890000]   o Single TX Queue support – ETH_DEF_TXQ=0
[    0.890000]   o TCP segmentation offload (TSO) supported
[    0.900000]   o Large Receive offload (LRO) supported
[    0.900000]   o Receive checksum offload supported
[    0.910000]   o Transmit checksum offload supported
[    0.910000]   o Network Fast Processing (Routing) supported – (Disabled)
[    0.920000]   o Driver ERROR statistics enabled
[    0.930000]   o Proc tool API enabled
[    0.930000]   o SKB Reuse supported – (Disabled)
[    0.930000]   o SKB Recycle supported – (Disabled)
[    0.940000]   o Rx descripors: q0=128
[    0.940000]   o Tx descripors: q0=532
[    0.950000]   o Loading network interface(s):
[    0.950000]      o register under mv88fx_eth platform
[    0.960000]      o eth0, ifindex = 2, GbE port = 0
[    0.960000]
[    0.960000] mvFpRuleDb (c45b1000): 1024 entries, 4096 bytes
[    0.970000] Counter=0, opIdx=6, overhead=16
[    0.970000] Counter=1, opIdx=2, overhead=0
[    0.980000] Counter=2, opIdx=1, overhead=18
[    0.980000] Counter=3, opIdx=2, overhead=0
[    0.990000] tun: Universal TUN/TAP device driver, 1.6
[    0.990000] tun: (C) 1999-2004 Max Krasnyansky 
[    1.000000] NAND device: Manufacturer ID: 0xad, Chip ID: 0xf1 (Hynix NAND 128MiB 3,3V 8-bit)
[    1.010000] Scanning device for bad blocks
[    1.060000] Using static partition definition
[    1.060000] Creating 5 MTD partitions on “nand_mtd”:
[    1.070000] 0x000000000000-0x000000200000 : “u-boot”
[    1.070000] 0x000000200000-0x000000500000 : “uImage”
[    1.080000] 0x000000500000-0x000000800000 : “uImage2”
[    1.080000] 0x000000800000-0x000001000000 : “failsafe”
[    1.090000] 0x000001000000-0x000008000000 : “root”
[    1.100000] UBI: attaching mtd4 to ubi0
[    1.100000] UBI: physical eraseblock size:   131072 bytes (128 KiB)
[    1.110000] UBI: logical eraseblock size:    126976 bytes
[    1.110000] UBI: smallest flash I/O unit:    2048
[    1.120000] UBI: sub-page size:              512
[    1.120000] UBI: VID header offset:          2048 (aligned 2048)
[    1.130000] UBI: data offset:                4096
[    1.350000] UBI: attached mtd4 to ubi0
[    1.360000] UBI: MTD device name:            “root”
[    1.360000] UBI: MTD device size:            112 MiB
[    1.360000] UBI: number of good PEBs:        896
[    1.370000] UBI: number of bad PEBs:         0
[    1.370000] UBI: max. allowed volumes:       128
[    1.380000] UBI: wear-leveling threshold:    4096
[    1.380000] UBI: number of internal volumes: 1
[    1.390000] UBI: number of user volumes:     1
[    1.390000] UBI: available PEBs:             0
[    1.400000] UBI: total number of reserved PEBs: 896
[    1.400000] UBI: number of PEBs reserved for bad PEB handling: 8
[    1.410000] UBI: max/mean erase counter: 1/0
[    1.410000] UBI: image sequence number: 0
[    1.420000] ehci_hcd: USB 2.0 ‘Enhanced’ Host Controller (EHCI) Driver
[    1.420000] ehci_marvell ehci_marvell.70059: Marvell Orion EHCI
[    1.430000] ehci_marvell ehci_marvell.70059: new USB bus registered, assigned bus number 1
[    1.440000] UBI: background thread “ubi_bgt0d” started, PID 452
[    1.470000] ehci_marvell ehci_marvell.70059: irq 19, io base 0xf1050100
[    1.490000] ehci_marvell ehci_marvell.70059: USB 2.0 started, EHCI 1.00
[    1.490000] usb usb1: configuration #1 chosen from 1 choice
[    1.500000] hub 1-0:1.0: USB hub found
[    1.500000] hub 1-0:1.0: 1 port detected
[    1.510000] xhci_hcd 0000:00:01.0: xHCI Host Controller
[    1.510000] xhci_hcd 0000:00:01.0: new USB bus registered, assigned bus number 2
[    1.520000] xhci_hcd 0000:00:01.0: irq 9, io mem 0xe0000000
[    1.530000] usb usb2: config 1 interface 0 altsetting 0 endpoint 0x81 has no SuperSpeed companion descriptor
[    1.540000] usb usb2: configuration #1 chosen from 1 choice
[    1.540000] hub 2-0:1.0: USB hub found
[    1.550000] hub 2-0:1.0: 4 ports detected
[    1.550000] Initializing USB Mass Storage driver…
[    1.550000] usbcore: registered new interface driver usb-storage
[    1.560000] USB Mass Storage support registered.
[    1.570000] usbcore: registered new interface driver ums-datafab
[    1.570000] usbcore: registered new interface driver ums-freecom
[    1.580000] usbcore: registered new interface driver ums-jumpshot
[    1.580000] usbcore: registered new interface driver ums-sddr09
[    1.590000] usbcore: registered new interface driver ums-sddr55
[    1.600000] usbcore: registered new interface driver ums-usbat
[    1.600000] mice: PS/2 mouse device common for all mice
[    1.610000] i2c /dev entries driver
[    1.620000] sdhci: Secure Digital Host Controller Interface driver
[    1.620000] sdhci: Copyright(c) Pierre Ossman
[    1.630000] mmc0: mvsdio driver initialized, using GPIO 27 for card detection
[    1.640000] usbcore: registered new interface driver usbhid
[    1.640000] usbhid: v2.6:USB HID core driver
[    1.650000] TCP cubic registered
[    1.650000] NET: Registered protocol family 17
[    1.660000] RPC: Registered udp transport module.
[    1.660000] RPC: Registered tcp transport module.
[    1.670000] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
[    1.740000] UBIFS: recovery needed
[    1.810000] UBIFS: recovery completed
[    1.820000] UBIFS: mounted UBI device 0, volume 0, name “rootfs”
[    1.820000] UBIFS: file system size:   110850048 bytes (108252 KiB, 105 MiB, 873 LEBs)
[    1.830000] UBIFS: journal size:       9023488 bytes (8812 KiB, 8 MiB, 72 LEBs)
[    1.840000] UBIFS: media format:       w4/r0 (latest is w4/r0)
[    1.840000] UBIFS: default compressor: lzo
[    1.850000] UBIFS: reserved for root:  0 bytes (0 KiB)
[    1.850000] VFS: Mounted root (ubifs filesystem) on device 0:11.
[    1.860000] Freeing init memory: 124K
[    4.230000] eth0: started
udhcpc (v1.16.1) started
HWADDR 00 0x25 0x31 0x04 0x12 0x05
PIP0 18
PIP1 5
cat: can’t open ‘/etc/resolv.conf’: No such file or directory
route: SIOCDELRT: No such process
grep: /etc/resolv.conf: No such file or directory
Sending discover…
Sending discover…
Sending discover…
HWADDR 00 0x25 0x31 0x04 0x12 0x05
PIP0 18
PIP1 5
No lease, forking to background
Loading gpio_keys.ko…
Loading ejectbutton.ko…
[   13.750000] IRQ 93 uses trigger mode 0; requested 3
[   13.760000] input: gpio-keys as /devices/platform/gpio-keys.0/input/input0
[   13.770000] xce_ebtn: Pogoplug series V4 eject button initialized.
[   13.920000] ufsd: module license ‘Commercial product’ taints kernel.
[   13.920000] Disabling lock debugging due to kernel taint
[   13.950000] ufsd: driver (8.6 (U86_S[2012-02-28-18:39:23]), LBD=ON, delalloc, ioctl) loaded at bf00c000
[   13.950000] NTFS support included
[   13.950000] Hfs+/HfsX support included
[   13.950000] For ‘CloudEngines_PogoPlug_2011-08-03’
Loading rt3070sta.ko:        [   14.280000] rtusb init rt2870 —>
[   14.290000] usbcore: registered new interface driver rt2870
Success
Loading xce.ko:              [   14.320000] Cloud Engines XCE Init [Version: 3.9.0.4]
[   14.320000] XCE: CPU MEMORY MAP:
[   14.320000] XCE:   — 0x00001000 – 0xbeffffff (3055 MB)  User Space Mappings
[   14.330000] XCE:   — 0xbf000000 – 0xbfffffff (  16 MB)  Kernel module space
[   14.340000] XCE:   — 0xc0000000 – 0xc7ffffff ( 128 MB)  Kernel direct-mapped ram
[   14.350000] XCE:   — 0xc8800000 – 0xe7ffffff ( 504 MB)  Kernel vmalloc space
[   14.350000] XCE:   — 0xe8000000 – 0xfeffffff ( 367 MB)  Kernel platform space
[   14.360000] XCE: CPU FEATURES:
[   14.360000] XCE:   — I Cache:         enabled
[   14.370000] XCE:   — D Cache:         enabled
[   14.370000] XCE:   — Branch Predict:  disabled
[   14.380000] XCE:   — MMU:             enabled
[   14.380000] XCE:   — Alignment Abort: enabled
[   14.390000] XCE: BLPARAMS:   — Loading properties [c4be3efc].
[   14.400000] XCE: BLPARAMS:   — MTD @ [c45c0c00].
[   14.400000] XCE: BLPARAMS: Locating parameter block…
[   14.410000] XCE: BLPARAMS: reading 2048 bytes @ a0000
[   14.410000] XCE: Loaded Property Size: 2048
[   14.420000] XCE:    – ‘cesvcid’ -> ‘UGZRQL3K3BXDWQ7MVKDECX8MAE’
[   14.420000] XCE:    – ‘ceboardver’ -> ‘PPV4A3’
[   14.430000] XCE:   — ICache Prefetch: enabled
[   14.430000] XCE:   — DCache Prefetch: enabled
[   14.440000] XCE:   — L2 Cache:        enabled
[   14.440000] XCE:   — L2 Prefetch:     disabled
[   14.450000] XCE:   — L2 Writethrough: disabled
[   14.450000] XCE:   — Write Allocate:  disabled
[   14.460000] XCE:   — Streaming:       disabled
[   14.460000] XCE: Current GPIO State:
[   14.460000] XCE:  GPIO L OUT:    0x01f18400
[   14.470000] XCE:  GPIO L OE:     0xfe004800
[   14.470000] XCE:  GPIO L BLINK:  0x00000000
[   14.480000] XCE:  GPIO L POL:    0x28000000
[   14.480000] XCE:  GPIO L IN:     0x11f00000
[   14.480000] XCE:  GPIO H OUT:    0x00000008
[   14.490000] XCE:  GPIO H OE:     0x00000005
[   14.490000] XCE:  GPIO H BLINK:  0x00000000
[   14.500000] XCE:  GPIO H POL:    0x00000000
[   14.500000] XCE:  GPIO H IN:     0x00000008
Success
Starting hbplug:             Success
/ # [   14.590000] XCE: BLPARAMS:   — Loading properties [c4b7becc].
[   14.600000] XCE: BLPARAMS:   — MTD @ [c45c0c00].
[   14.600000] XCE: BLPARAMS: Locating parameter block…
[   14.610000] XCE: BLPARAMS: reading 2048 bytes @ a0000
[   14.620000] XCE: BLPARAMS: reading 2048 bytes @ a0800
[   14.620000] XCE: BLPARAMS: reading 2048 bytes @ a1000
[   14.630000] XCE: BLPARAMS: reading 2048 bytes @ a1800
[   20.000000] XCE: XCE: LED -> DISCONNECTED
继续阅读

发表在 Linux | 留下评论

ramfs,tmpfs, rootfs and initramfs

ramfs是什么



ramfs是一个非常简单的文件系统,它输出Linux的磁盘缓存机制(页缓存和目录缓存)作为一个大小动态的基于内存的文件系统。



通常,所有的文件由Linux被缓存在内存中。页的数据从保持在周围以防再次需要的后备存储(一般被挂载的是块设备文件系统)中读取,并标记为可用(空闲)以防虚拟内存系统(Virtual Memory System)需要这些内存作为别用。类似的,在数据写回后备存储时,数据一写回文件就立即被标记为可用,但周围的缓存被保留着直至VM(虚拟机)重新分配内存。一个类似的机制(目录缓存)极大的加快了对目录的访问。



ramfs并没有后备存储。文件写入ramfs象往常一样,来分配目录和页的缓存,但这里并没有地方可写回它们。这意味着页的数据不再标记为可用,因此当希望回收内存时,内存不能通过VM来释放。



实现ramfs所需的代码总量是极少的,因为所有的工作由现有的Linux缓存结构来完成。实际上,你现正在挂载磁盘缓存作为一个文件系统。据此,ramfs并不是一个可通过菜单配置项来卸载的可选组件,它可节省的空间是微不足道的。



ramfs和ramdisk



旧的”内存磁盘”机制在一个内存空间中创建一个合成块设备并使用它作为一个文件系统的后备存储。这个块设备是固定大小的以至于挂载在它上面的文件系统也是固定大小的。除创建和销毁目录外,使用一个内存磁盘并不需要从假的块设备到页缓存拷贝内存数据(和拷贝更改回退)。另外,它需要一个文件系统驱动 (如,ext2)来格式和解释这些数据。



与ramfs相比较,这些废弃的内存(和内存总线带宽)为CPU造成了不必要的工作并污染了CPU缓存。(这里有个技巧通过使用页表单来避免这个拷贝,但是它们难以理解并且代价反而变的与拷贝一样昂贵。)更为重要的是,由于所有的文件都通过页和目录缓存进行访问,全部的工作ramfs都要执行。内存磁盘是简单且多余的,ramfs在内部更为简单。



另一个理由是:ramdisks是半过时的,它引进的回环设备提供一个更灵活和方便的方式从文件而不是从大块的内存中来创建一个合成块设备。

参见losetup (8) 来获得有关细节。



ramfs和tmpfs



ramfs的一个不利之处是你将保留写回到ramfs的数据直至你填补所有的内存,并且VM不能释放它,因为VM考虑到文件将写回后备存储(而不是交换空间),但是ramfs并不能获得任何的后备存储。据此,只有root(或者一个受信任的用户)可允许回写到一个ramfs挂载中。



一个ramfs派生出tmpfs来添加大小的限制以及回写数据到交换空间的能力。普通用户可以允许回写到tmpfs挂载中。

参见Documentation/filesystems/tmpfs.txt来获得更多信息。



rootfs是什么



rootfs是一个特定的ramfs(或tmpfs,如果那被启用)的实例,它始终存在于2.6的系统。你不能卸载rootfs,这个理由近似于你不能杀死init进程。它小巧且简单的为内核确保某些列表不能为空,而不是拥有特定的代码来检查和处理一个空列表。



大多数的系统挂载另一个文件系统到rootfs并忽略它。一个空白ramfs实例的空间总量占用是极小的。



initramfs是什么



所有的2.6 Linux内核包含了一个gzip压缩过的”cpio”格式存档,当内核启动时它将被提取到rootfs。在提取之后,内核检测rootfs是否包含了一个”init”文件,如果包含就来执行它并设置PID为1。如果找到,这个init进程将负责引导系统的其余内容,包含了要寻找和挂载的真正根设备(若有的话)。如果rootfs在提取cpio存档以后并不包含一个init程序,内核将失败并通过旧的代码来寻找和挂载一个根分区,接着执行一些/sbin /init的变种。



与旧的initrd有以下几点不同:

– 旧的initrd通常是一个独立的文件,而initramfs存档是连接到linux内核映像的。(Linux系统目录-*/usr 在构建时就是为了生成这个存档)



– 旧的initrd文件是一个gzip压缩过的文件系统映像(在一些文件格式,如ext2,需要构建一个驱动到内核),而这个新的initramfs存档是一个gzip压缩过的cpio存档(象tar一样简单,参见cpio(1) and Documentation/early-userspace/buffer-format.txt)。内核的cpio提取代码不仅极少,而且init文本和数据可以在启动过程中被丢弃。



– 程序通过旧的initrd(叫做/initrd,而不是/init)运行一些设定并接着返回内核,而init程序从initramfs并不预计返回内核。(如果/init需要手工关闭并控制它,可以与一个新的根设备一起覆盖挂载 / 并执行另一个init程序。参见switch_root utility的后部分)



– 当切换到另一个根设备,initrd会pivot_root并且接着卸载内存磁盘。但是initramfs是rootfs:你可以不用 pivot_root rootfs和卸载它。而是删除除rootfs之外的所有东西来释放空间(find -xdev / -exec rm ‘{}’ ‘;’),与新的根(cd /newmount; mount –move . /; chroot .)一起覆盖挂载rootfs,附加stdin/stdout/stderr到新的/dev/console并执行新的init。



由于这是一个非常谨慎的进程(以及在你运行它们之前涉及到删除命令),klibc包为你引进了一个帮助程序(utils/run_init.c)来做这些。大部分其他软件包(如,busybox)已命名在此命令”switch_root”中。



提供 initramfs



v2.6 内核构建进程总是创建一个gzip压缩过的cpio格式的initramfs存档并连接它到生成的内核二进制文件。默认的,这些存储是空的(在x86上占用134 bytes)



配置选项CONFIG_INITRAMFS_SOURCE(存在于menuconfig的General Setup选项和usr/Kconfig中)可为initramfs存档使用特定的一个源文件,它自动合并到生成的二进制文件中。这个选项可以指定一个现有的gzip压缩的cpio存档,这个存档可以包含一个目录文件到或者是一个文本文件详述,如下面的示例:



dir /dev 755 0 0

nod /dev/console 644 0 0 c 5 1

nod /dev/loop0 644 0 0 b 7 0

dir /bin 755 1000 1000

slink /bin/sh busybox 777 0 0

file /bin/busybox initramfs/busybox 755 0 0

dir /proc 755 0 0

dir /sys 755 0 0

dir /mnt 755 0 0

file /init initramfs/init.sh 755 0 0



在文件格式之上运行”usr/gen_init_cpio”(在构建内核之后)来获得一个用法文档。



一个高级的配置文件是root访问不需要在新的存档上设置权限或者创建设备节点。(注意示例的那两个”file”期望在linux-2.6.*目录下,在”initramfs”目录中找到名为”init.sh”和”busybox”的文件。参见Documentation/early- userspace/README 以获得更多细节。)



内核并不依赖外部的cpio工具。如果你指定一个目录而不是一个配置文件,内核的构建结构将从那个目录(usr/Makefile 调用

scripts/gen_initramfs_list.sh)创建一个配置文件,并封装该目录来使用配置文件(通过释放它到从 usr/gen_init_cpio.c 创建的 usr/gen_init_cpio)。在内核构建时cpio创建的代码是完全独立的,在内核开启时提取器也是(完全)独立的。



你唯一可能需要为创建或提取你自己的cpio文件以提供给内核构建(而不是一个配置文件或目录)而安装外部的cpio工具。



以下的命令行可提取一个cpio映像(不管是通过以上脚本或是通过内核构建成的)回退到它的组成文件:

cpio -i -d -H newc -F initramfs_data.cpio –no-absolute-filenames



以下的shell脚本可创建一个预制的cpio存档,你可以使用在上述的配置文件中:



#!/bin/sh



# Copyright 2006 Rob Landley <rob@landley.net> and TimeSys Corporation.

# Licensed under GPL version 2



if [ $# -ne 2 ]

then

    echo “usage: mkinitramfs directory imagename.cpio.gz”

    exit 1

fi



if [ -d “$1” ]

then

    echo “creating $2 from $1”

    (cd “$1”; find . | cpio -o -H newc | gzip) > “$2”

else

    echo “First argument must be a directory”

    exit 1

fi



注意:如果你是按照cpio的man页做的,那么它包含的一些不良建议将会破坏你的initramfs存档。它说”生成文件名列表的一个典型方式是使用 find命令,你应该提供-depth选项来搜索”。而在创建initramfs.cpio.gz映像时不要这么做,因为它并不可行。Linux内核的 cpio提取器不会在一个不存在的目录中创建文件,因此目录项必须在文件被提取到该目录之前被提取。以上脚本保证了它们的顺序正确性。



外部initramfs映像



如果内核有启用initrd支持,一个外部的cpio.gz存档也可替换一个2.6 内核的initrd。既然这样,内核将自动检测文件类型(initramfs, 而不是initrd)并在尝试运行/init前,提取外部的cpio存档到rootfs。



initramfs有内存效率的优势(没有内存磁盘块设备),而initrd可单独封装(如果你有非GPL许可协议的代码,而你想从initramfs运行,这还是不错的。不要与GPL许可的二进制的Linux内核混为一谈)。



外部initramfs映像也可以用来补充内核内建的initramfs映像。外部存档文件将覆盖与内建initramfs存档中任意不一致的文件。一些发行商也偏爱定制一个单一内核映像和特定initramfs映像,而不用重编译。



initramfs的内容



一个initramfs存档是一个完整独立的Linux根文件系统。如果你还不能理解共享库、设备和路径,你需要获得一个小的根文件系统来启动和运行,这里有一些参考资料:

http://www.tldp.org/HOWTO/Bootdisk-HOWTO/

http://www.tldp.org/HOWTO/From-PowerUp-To-Bash-Prompt-HOWTO.html

http://www.linuxfromscratch.org/lfs/view/stable/



软件包”klibc”(http://www.kernel.org/pub/linux/libs/klibc)被设计为一个极小的C库来静态连接早期的用户空间代码,以及一些相关的工具。它是BSD授权。



我使用uClibc (http://www.uclibc.org)和busybox (http://www.busybox.net)。这些分别是LGPL和GPL授权。(一个独立的initramfs软件包被计划在busybox 1.3 release。)



从理论上说你可以使用glibc,但是对于小型嵌入式系统象这样使用并适合。(一个”hello world”程序静态连接glibc将近400k。用uClibc的话它是7k。还要注意,glibc dlopens libnss作为名称查找,即使是使用静态连接。)



一个好的开头是获得initramfs来运行一个静态连接的”hello world”程序作为init,并在一个类似qemu(www.qemu.org)的仿真器或用户模式的Linux中测试它,象这样:

cat > hello.c << EOF

#include <stdio.h>

#include <unistd.h>



int main(int argc, char *argv[])

{

    printf(“Hello world!/n”);

    sleep(999999999);

}

EOF

gcc -static hello.c -o init

echo init | cpio -o -H newc | gzip > test.cpio.gz

# Testing external initramfs using the initrd loading mechanism.

qemu -kernel /boot/vmlinuz -initrd test.cpio.gz /dev/zero



当调试一个普通根文件系统时,能够用”init=/bin/sh”来启动将是不错的。与initramfs等价的是”rdinit=/bin/sh”,而且它很有用。



为什么是cpio而不是tar?



这个决定的发布是在2001年12月。讨论浏览在这里:

http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1538.html



并且催生了第二件事情(tar与cpio的比较),浏览这里

http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1587.html



快速且直接的总结版本(这些是无法替代上述内容的阅读的):

1) cpio是一个标准。它十来岁了(从 AT&T起),并已被广泛应用在Linux上(在RPM中,Red Hat的设备驱动磁盘上)。这里有从1996年起有关它的Linux日志:

http://www.linuxjournal.com/article/1213



它并没有象tar一样流行,因为传统的cpio命令行工具要求使用极可怕的命令行。同时没有其他有关存档格式的方式,并有可选的工具。如:

http://freshmeat.net/projects/afio/



2) cpio存档格式是由内核选择的,它比(许多国家的)任意的tar存档格式都简单且干净(并极容易来创建和解析)。完整的initramfs存档格式说明在buffer-format.txt,创建在usr/gen_init_cpio.c,并提取在init/initramfs.c。所有三个可阅读的文本一起不到26k。



3) GNU项目使用tar标准似乎是与Windows使用zip的标准相关。Linux并不是它们中任一一个,并自由的作出了自己的技术决策。



4) 由于这是一个内核的内部格式,它可以很容易做一些更新。内核提供它自己的工具来创建和提取这个格式。使用现有的标准是可取的,但不是必要的。



5) Al Viro 作出决定(引用: “tar is ugly as hell and not going to be supported on the kernel side”):

http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1540.html



解释它的理由:

http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1550.html

http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1638.html



最重要的是,设计和实现initramfs的代码。



发展的方向



当前(2.6.16), initramfs总被编译进,但并没总被使用。内核做到回退到原来的启动代码只需initramfs中不包含一个/init程序。回退

是原来的代码,以此确保一个平滑的过渡并允许尽早的开启功能逐步移动到”前期用户空间”(即initramfs)。



移动到前期用户空间是必要的,因为寻找和挂载真正的根设备是复杂的。根分区可以跨多个设备。它们可在网络上进行(要求dhcp,设定一个特定MAC地址,登录到一台服务器等)。它们可用在可移动媒体,动态分配主/次号以及要求udev执行清理的持续命名的问题。它们可被压缩、加密、写时拷贝,回环挂载、异常分区等。



这种复杂性(必将包含的策略)是在用户空间的处理的正确性。klibc和busybox/uCli 继续阅读

发表在 Linux | 留下评论

关于kernel和rootfs的加密

在gzip解包前,加了个 解密函数。

同时对 initrd.gz 进行加密。(事先对initrd加密,在kernel中的init/initramfs.c中解密)
继续阅读

发表在 Linux | 一条评论

Unix系列shell程序编写(下)

Until语句

  While语句中,只要某条件为真,则重复执行循环代码,until语句正好同while相反,该语句使循环代码重复执行,直到遇到某一条件为真才停止。

Until语句的结构如下: 
until command 
   do 
     command 
     command 
     … … 
   done

  可以用until语句替换上面备份程序的while语句,完成同样的功能:

until [ \$ANS != Y -a \$ANS != y ]

for 循环 
   在介绍for循环之前,我们要学个非常有用的Unix命令:shift。我们知道,对于位置变量或命令行参数,其个数必须是确定的,或者当Shell程序不知道其个数时,可以把所有参数一起赋值给变量\$*。若用户要求Shell在不知道位置变量个数的情况下,还能逐个的把参数一一处理,也就是在\$1后为\$2,在\$2后面为\$3等。在 shift命令执行前变量\$1的值在shift命令执行后就不可用了。

示例如下:

#测试shift命令(x_shift.sh) 
until [ \$# -eq 0 ] 
do 
echo “第一个参数为: \$1 参数个数为: \$#” 
shift 
done 
执行以上程序x_shift.sh: 
\$./x_shift.sh 1 2 3 4

结果显示如下:

第一个参数为: 1 参数个数为: 3 
第一个参数为: 2 参数个数为: 2 
第一个参数为: 3 参数个数为: 1 
第一个参数为: 4 参数个数为: 0从上可知shift命令每执行一次,变量的个数(\$#)减一,而变量值提前一位,下面代码用until和shift命令计算所有命令行参数的和。

#shift上档命令的应用(x_shift2.sh) 
if [ \$# -eq 0 ] 
then 
echo “Usage:x_shift2.sh 参数” 
exit 1 
fi 
sum=0 
until [ \$# -eq 0 ] 
do 
sum=`expr \$sum + \$1` 
shift 
done 
echo “sum is: \$sum”

执行上述程序:

\$x_shift2.sh 10 20 15

其显示结果为:

45

  shift命令还有另外一个重要用途,Bsh定义了9个位置变量,从\$1到\$9,这并不意味着用户在命令行只能使用9个参数,借助shift命令可以访问多于9个的参数。

  Shift命令一次移动参数的个数由其所带的参数指定。例如当shell程序处理完前九个命令行参数后,可以使用shift 9命令把\$10移到\$1。

  在熟悉了shift命令后,我们一起看看,Bsh程序中非常有用的for循环语句,这种循环同上面说的while和until循环不同,for语句中的循环是否执行并不由某个条件的真和假来决定,决定for循环是否继续的条件是参数表中是否还有未处理的参数。

For语句的结构如下:

for variable in arg1 arg2 … argn 
do 
command 
command 
… … 
done

下面是for循环的简单例子:

for LETTER in a b c d 
do 
echo \$LETTER 
done

程序执行结果如下:




d

在上面计算参数和的例子中,我们可以用for循环,实现如下:

#测试 for 程序(x_for.sh)

if [ \$# -eq 0 ] 
then 
    echo “Usage:x_for.sh 参数… …” 
    exit 1 
fi 
sum=0 
for I in \$* 
do 
    sum=`expr \$sum + \$I` 
done 
echo “sum is: \$sum”

中断循环指令

  在程序循环语句中,我们有时候希望遇到某中情况时候结束本次循环执行下次循环或结束这个循环,这就涉及到两条语句:continue和break。continue命令可使程序忽略其后循环体中的其他指令,直接进行下次循环,而break命令则立刻结束循环,执行循环体后面的的语句。

#测试continue 
I=1 
while [ \$I -lt 10 ] 
do 
   if [ \$I -eq 3 ] 
   then 
     continue 
   fi 
   if [ \$I -eq 7 ] 
   then 
     break 
   fi 
   echo “\$Ic” 
done

执行上面程序,结果如下:

12456789

与或结构

使用与/或结构有条件的执行命令

  Shell程序中可以使用多种不同的方法完成相同的功能,例如until和while语句就可以完成相同的功能,同样,除了if-then-else结构可以使命令有条件的执行外,\$\$和||操作符也能完成上述功能。在C语言中这两个操作符分别表示逻辑与和逻辑或操作。在Bourne Shell中,用&&连接两条命令的含义只有前面一条命令成功执行了,后面的命令才会执行。

  &&操作的形式为:

    command && command

  例如语句:

    rm \$TEMPDIR/* && echo “Files successfully removed”

  只有rm命令成功执行以后,才会执行echo命令。若用if-then语句实现上述功能,形式为:

    if rm \$TEMPDIR/* 
     then 
       echo “Files successfully removed” 
     fi 
   相反,用||连接两条命令的含义为只有第一条命令执行失败才执行第二条命令,例如:

    rm \$TEMPDIR/* || echo “File were not removed”

  上面语句的等价形式为:

    if rm \$TEMPDIR/* 
     then 
       : 
     else 
       echo “Files were not removed” 
     fi 
   这两种操作符可以联合使用,如在下面的命令行中,只有command1和command2执行成功后,command3才会执行:

    command1 && command2 && command3

  下面的命令行表示只有command1成功执行,command2不成功执行时,才会执行command3。

  &&和||操作符可以简化命令条件执行的格式,但一般只用于一条命令的条件执行。如果许多命令都使用这两个操作符,那么整个程序的可读性将变的很差,所以在多条命令的条件执行时,最好采用可读性好的if语句。

函数

  现在我们介绍Shell程序中的函数部分,基本上任何高级语言都支持函数这个东西,能让我们胜好多事情的东西,至少省的频繁的敲击相同的东西,好了come on 
Shell程序中的函数

  函数又叫做子程序,可以在程序中的任何地方被调用,其格式如下:

  函数名字() 
   { 
     command 
     … … 
     command; 
   }

  Shell程序的任何地方都可以用命令 “函数名字” 调用,使用函数的好处有两点,一点是使用函数可以把一个复杂的程序化为多个模块,易于管理,符合结构化程序的设计思想,另一个好处是代码的重用。

  Shell函数和Shel程序比较相似,它们的区别在于Shell程序在子Shell中运行,而Shell函数在当前Shell中运行。因此,在当前Shell中可以看到Shell函数对变量的修改。在任何Shell中都可以定义函数,包括交互式Shell。

  例如:

    \$dir() {ls -l;}

    结果是我们在\$后面打dir,其显示结果同ls -l的作用是相同的。该dir函数将一直保留到用户从系统退出,或执行了如下所示的unset命令: 
     \$unset dir 
     下面的例子说明了函数还可以接受位置参数:

    \$dir(){_ 
     >echo “permission    ln owner   group    file sz last access 
     >ls -l \$*; 
     >}

    运行 dir a* 看产生什么结果

    参数a*传递到dir函数中并且代替了\$*

    通常Shell程序将在子Shell中执行,该程序对变量的改变只在子Shell中有效而在当前Shell中无效。”.”命令可以使Shell程序在当前Shell中执行。用户可以在当前Shell中定义函数和对变量赋值。通常用下面命令来重新初使化.profile对Shell环境的设置。 
     \$ . .profile 
   由于看到这部分相对简单,我们还是顺便说说trap好了

使用trap命令进行例外处理

  用户编写程序在程序运行时可能会发生一些例外情况,比如执行该程序的用户按中断键或使用kill命令,或者控制终端突然与系统断开等。unix系统中的上述情况会使系统向进程发一个信号,通常情况下该信号使进程终止运行。有时侯用户希望进程在接到终止信号时进行一些特殊的操作。若进程在运行时产生一些临时文件,又因接受到的信号而终止。那么该进程产生的临时文件将保留下来。在bsh中,用户可以使用trap命令修改进程接收到终止信号时进行的默认操作。 
   trap命令格式如下:

     trap command_string signals

多数系统中共有15种发给进程的信号,默认情况下大多数信号都会使程序终止。用户最好查阅自己系统的文挡,看看本系统内使用的信号种类。除了信号为9(真正的kill信号)不能使用trap命令外,其他信号所带来的操作都可以用trap命令进行指定。下面是trap命令中经常使用的几种信号:

    信号   功能 
     1     挂起 
     2    操作中断 
     15    软终止(kill信号)

  若命令串中包含不只一条命令,必须使用引号将整个命令括起来,具体是单引号还是双引号,由用户是否需要变量替换决定。” “替换,’ ‘不替换。

  使用下面trap命令可以使程序在接收到挂起、中断或kill信号时,首先把临时文件删除,然后退出:

    trap “rm \$TEMPDIR/* \$\$;exit” 1 2 15

  在上面例子中,当Shell读取trap命令时,首先对\$TEMPDIR和\$\$进行变量替换,替换之后的命令串将被保存在trap表中,若上例中trap命令使用单引号时,trap命令执行时候,不进行变量替换,而把命令串 rm \$TEMPDIR/* \$\$;exit 放到trap表中,当检测到信号时,程序解释执行trap表中的命令串,此时进行变量替换。前面变量\$TEMPDIR和\$\$的值为执行trap指令时候的值,后一种情况中变量的值为程序接收到信号时候的值,所以 “、’一定要区分仔细。

  下面命令的含义为用户按二次中断键后,程序才终止:

    trap ‘trap 2’ 2

  一般trap命令中的命令串中几乎都包含exit语句,上面rm的例子若无exit语句,接收到信号rm命令执行完后程序将挂起。但有时用户也需要程序在接到信号后挂起,例如当终端和系统断开后,用户发出挂起信号,并执行空命令,如下:

    trap : 1

  若用户想取消前trap指令设置的命令串,可以再执行trap命令,在命令中不指定命令串表示接收到信号后进行默认的操作,命令如下: 
     trap 1

规范Shell

获取UNIX类型的选项:

  unix有一个优点就是标准UNIX命令在执行时都具有相同的命令行格式:

  command -options parameters

  如果在执行Shell程序也采用上述格式,Bourne Shell中提供了一条获取和处理命令行选项的语句,即getopts语句。该语句的格式为:

  getopts option_string variable

  其中option_string中包含一个有效的单字符选项。若getopts命令在命令行中发现了连字符,那么它将用连字符后面的字符同option_string相比较。若有匹配,则把变量variable的值设为该选项。若无匹配,则variable设为?。当getopts发现连字符后面没有字符,会返回一个非零的状态值。Shell程序中可以利用getopts的返回值建立一个循环。

  下面代码说明了date命令中怎么使用getopts命令处理各种选项,该程序除了完成unix的标准命令date的功能外,还增加了许多新的选项。 
   #新date程序 
   if [ \$# -lt 1 ] 
   then 
     date 
   else 
     while getopts mdyDHMSTJjwahr OPTION 
     do 
       case \$OPTION 
       in 
         m)date ‘+%m’;; 
         d)date ‘+%d’;; 
         y)date ‘+%y’;; 
         D)date ‘+%D’;; 
         H0date ‘+%H’;; 
         M)date ‘+%M’;; 
         S)date ‘+%S’;; 
         T)date ‘+%T’;; 
         j)date ‘+%j’;; 
         J)date ‘+%y%j’;; 
         w)date ‘+%w’;; 
         a)date ‘+%a’;; 
         h)date ‘+%h’;; 
         r)date ‘+%r’;; 
         ?)echo “无效的选项!\$OPTION”;; 
       esac 
     done 
   fi 
   有时侯选项中还带一个值,getopts命令同样也支持这一功能。这时需要在option_string中选项字母后加一个冒号。当getopts命令发现冒号后,会从命令行该选项后读取该值。若该值存在,那么将被存在一个特殊的变量OPTARG中。如果该值不存在,getopts命令将在OPTARG中存放一个问号,并且在标准错误输出上显示一条消息。

  下面的例子,实现拷贝一个文件,并给文件赋一个新的名字。-c选项指定程序拷贝的次数,-v选项要求显示新创建文件的文件名。

  #–拷贝程序

  COPIES=1 
   VERBOSE=N 
   while getopts vc:OPTION 
   do 
     case \$OPTION 
     in 
       c)COPIES=\$OPTARG;; 
       v)VERBOSE=Y;; 
       ?)echo “无效参数!” 
        exit 1;; 
     esac 
   done 
   if [ \$OPTIND -gt \$# ] 
   then 
     echo “No file name specified” 
     exit 2 
   fi 
   shift ‘expr \$OPTIND – 1’ 
   FILE=\$1 
   COPY=0 
   while [ \$COPIES -gt \$COPY ] 
   do 
     COPY=’expr \$COPY + 1′ 
     cp \$FILE \$ {FILE} \$ {COPY} 
     if [ VERBOSE = Y } 
     then 
       echo \${FILE} \$ {COPY} 
     fi 
   done

规范Shell:

  我们知道环境变量PS1是提示符,看下面程序chdir: 
   if [ ! -d “\$!” ] 
   then 
     echo “\$1 is not a Directory” 
     exit 1 
   fi 
   cd \$1 
   PS1=”‘pwd’>” 
   export PS1

  我们执行:

    \$chdir /usr/ice666

  结果提示符号变成/usr/ice666>了吗?没有,为什么?

  原因在于:chdir在子Shell中执行,变量PS1的修改在当前Shell中也不会起作用,若要chdir完成意想中的功能,必须在当前Shell中执行该命令。最好的方法就是把其改成一个函数并且在.profile文件中定义。但若要把函数放到单个文件中并在当前Shell中执行,则需要使用 . 命令,并将chdir重写成一个函数,把其中的exit改写成return。下面代码是 .ice_ps的内容:

  #–提示符 
   chdir() 
   { 
   if [ !-d “\$1” ] 
   then 
     echo ” \$1 is not a directory” 
     return 
   fi 
   cd \$1 
   PS1=”‘pwd’>” 
   export PS1; 
   }

  然后我们在.profile文件中加入下面语句

  .ice_ps

  然后在切换目录的时候,我们用chdir命令,结果是什么呢,自己实验好了!   
调试Shell程序

1>调试shell程序

  用户刚编写完Shell程序中,不可避免的会有错误,这时我们可以利用Bsh中提供的跟踪选项,该选项会显示刚刚执行的命令及参数。用户可以通过set命令打开-x选项或在启动Shell使用-x选项将Shell设置成跟踪模式。例如有下面代码ice_tx:

  if [ \$# -eq 0 ] 
   then 
     echo “usage:sumints integer list” 
     exit 1 
   fi 
   sum=0 
   until [ \$# -eq 0 ] 
   do 
     sum=’expr \$sum + \$1′ 
     shift 
   done 
   echo \$sum

  我们用跟踪模式运行:

  \$sh -x ice_tx 2 3 4 
   结果显示: 
   +[ 3 -eq 0 ] 
   +sum=0 
   +[ 3 -eq 0 ] 
   +expr 0+2 
   +sum=2 
   +shift 
   +[ 2 -eq 0 ] 
   +expr 2+3 
   +sum=5 
   +shift 
   +[ 1 -eq 0 ] 
   +expr 5+4 
   +sum=9 
   +[ 0 -eq 0 ] 
   +echo 9 
   9

  从上面可以看出,跟踪模式下Shell显示执行的每一条命令以及该命令使用的变量替换后的参数值。一些控制字如if、then、until等没显示。 
2>命令分组

  Shell中若干命令可以组成一个单元一起执行。为了标识一组命令,这些命令必须放到”()”或”{}”中。放在”()”中的命令将在子Shell中运行,而放在”{}”中的命令将在当前Shell中运行。子Shell中运行的命令不影响当前Shell的变量。当前Shell中运行的命令影响当前Shell的变量。

  \$NUMBER=2 
   \$(A=2;B=2;NUMBER=’expr \$A+\$B’;echo \$NUMBER) 
   结果为:4 
   \$echo \$NUMBER 
   结果为:2 
   如果把上面的()变成{},结果会是怎么样的呢?

3>使用Shell分层管理器shl

  UNIX是一个多道程序设计的操作系统,一些UNIX系统利用这一特性提供了Shell层次管理器shl。使用shl用户一次可以打开多个层次的Shell,其中活跃的Shell可以从终端上获得输入。但所有Shell的输出都可在终端上显示,除非显示被禁止。

  多个Shell中有一个为shl,当用户在某个Shell中工作时,可以通过使用特殊字符(一般为Ctrl+z)返回shl。为了同其他Shell区别,shl中提示符为”>>>”。当用户工作在Shell层次管理器中时,可以创建、激活和删除Shell,下面是shl中使用的命令。

  create name    产生名为name的层次 
   delete name    删除名为name的层次 
   block name     禁止名为name的层次的输出 
   unblock name    恢复名为name的层次的输出 
   resume name    激活名为name的层次 
   toggle       激活近来经常使用的层次 
   name        激活名为name的层次

  layers [-l] name  对于表中的每个层次,显示其正在运行的进程的进程号,-l选项要求显示详细信息。

  help        显示shl命令的帮助信息 
   quit        退出shl以及所有被激活的层次 
总结

  在前面我们主要介绍了sh的变量、基本语法、程序设计等。如果掌握了这些内容,在学习其他UNIX下编程语言的时候,相信有一定的好处,我们说了,在大多数的UNIX中都提供Bourn Shell,而且很少有象sh这样强大的脚本编辑语言了,是系统管理员和程序员的一笔财富,并且不需要额外的软件环境,对文件等处理借助unix命令,实现起来比c实现还要简单。

  继续阅读

发表在 Linux | 留下评论

Unix系列shell程序编写(上)

*Shell是什么? 



  任何发明都具有供用户使用的界面。UNIX供用户使用的界面就是Shell(DOS的command熟悉吧,但UNIX的要强大的多)。 

Shell为用户提供了输入命令和参数并可得到命令执行结果的环境。 



  为了不同的需要,UNIX提供了不同的Shell。现在的UNIX大部分都支持BourneShell,以下教程就以BourneShell(Bsh)为例,一步步的领略UNIX 

Shell的强大功能,占先其强大魅力,达到更方便灵活的管理、应用UNIX的目的。 



  1.UNIX内核和Shell的交互方法 



  启动UNIX时,程序UNIX(内核)将被调入计算机内存,并一直保留在内存中直到机器关闭。在引导过程中,程序 

init将进入后台运行一直到机器关闭。该程序查询文件/etc/inittab,该文件列出了连接终端的各个端口及其特征。当发现一个活动的终端 时,init程序调用getty程序在终端上显示login等登陆信息。(username和passwd),在输入密码后, 

getty调用login进程,该进程根据文件/etc/passwd的内容来验证用户的身份。若用户通过身份验证,login进程 

把用户的home目录设置成当前目录并把控制交给一系列setup程序。setup程序可以是指定的应用程序,通常setup程序 

为一个Shell程序,如:/bin/sh 即Bourne Shell(command出来了,呵呵)。 



  得到控制后,Shell程序读取并执行文件/etc/.profile以及.profile。这两个文件分别建立了系统范围内的和 

该用户自己的工作环境。最后Shell显示命令提示符,如$。(这是以bsh为例,若是csh,为.cshrc,ksh为.kshrc,bash为.bashrc等等) 

    



  注不妨把/etc/.profile和.profile看成DOS的autoexec.bat 或 

config.sys文件) 



  当shell退出时,内核把控制交给init程序,该程序重新启动自动登陆过程。有两种方法使shell退出,一是用户执行exit命令,二是 

内核(例如root用kill命令)发出一个kill命令结束shell进程。shell退出后,内核回收用户及程序使用的资源。 



  用户登陆后,用户命令同计算机交互的关系为:命令进程—>Shell程序—>UNIX内核—>计算机硬件。当用户输入一个命令,如$ls, 

Shell将定位其可执行文件/bin/ls并把其传递给内核执行。内核产生一个新的子进程调用并执行/bin/ls。当程序执行完毕后,内核取消 

该子进程并把控制交给其父进程,即Shell程序。例如执行: 



    $ps 



    该命令将会列出用户正在执行的进程,即Shell程序(下来详细说说,别急现在)和ps程序。若执行: 



    $sleep 10 & 

    $ps 



  其中第一条命令将产生一个在后台执行的sleep子进程。ps命令执行时会显示出该子进程。 



  每当用户执行一条命令时,就会产生一个子进程。该子进程的执行与其父进程或Shell完全无关,这样可以使Shell去做其他工作。(Shell只是把用户的意图告诉内核,然后该干嘛干嘛) 

现在windows有个计划任务(在固定的时间,日期自动执行某任务),其实UNIX很早就有这个功能了,也就是所谓的Shell的自动执行。一些UNIX 

资源,如cron可以自动执行Shell程序而无需用户的参与,(这个功能好象在/var/spool/crotab目录里)。 



Crontab 程序对于系统管理员来说是非常有用的。Cron 

服务用于计划程序在特定时间(月、日、周、时、分)运行。我们以root的crontab 为例。根用户的 

crontab 文件放在 /var/spool/crontab/root 中,其格式如下: 



  (1)  (2)  (3)  (4)  (5)  (6) 

   0   0   *   *   3   /usr/bin/updatedb 

      1. 分钟 (0-60) 

      2. 小时 (0-23) 

      3. 日 (1-31) 

      4. 月 (1-12) 

      5. 星期 (1-7) 

      6. 所要运行的程序 

  2.Shell的功能和特点 

  1>命令行解释 

  2>使用保留字 

  3>使用Shell元字符(通配符) 

  4>可处理程序命令 

  5>使用输入输出重定向和管道 

  6>维护一些变量 

  7>运行环境控制 

  8>支持Shell编程 



  对于”命令行解释”就不多说了,就是在shell提示符(例如:”$”,”%”,”#”等)后输入一行unix命令,Shell将接收用户的输入。 



  ”使用保留字”:Shell有一些具有特殊意义的字,例如在Shell脚本中,do,done,for等字用来控制循环操作,if,then等控制条件操作。 

保留字随Shell环境的不同而不同。 



  ”通配符”:* 匹配任何位置 

       ? 匹配单个字符 

       [] 匹配的字符范围或列表 例如: 

        

          $ls [a-c]* 

          

          将列出以a-c范围内字符开头的所有文件 

          $ls [a,m,t]* 

         将列出以e,m或t开头的所有文件 



  ”程序命令” 

:当用户输入命令后,Shell读取环境变量$path(一般在用户自己的.profile中设置),该变量包含了命令可执行文件可能存在的目录列表。 

shell从这些目录中寻找命令所对应的可执行文件,然后将该文件送给内核执行。 



  ”输入输出重定向及管道” :重定向的功能同DOS的重定向功能: 



     “>” 重定向输出 

     “<” 重定向输入 



  而管道符号,是unix功能强大的一个地方,符号是一条竖线:”|”,用法: 

command 1 | command 2 他的功能是把第一个命令command 1执行的结果作为command 

2的输入传给command 2,例如: 



    $ls -s|sort -nr|pg 



  该命令列出当前目录中的所有文件,并把输出送给sort命令作为输入,sort命令按数字递减的顺序把ls的输出排序。然后把排序后的 

内容传送给pg命令,pg命令在显示器上显示sort命令排序后的内容。 



  ”维护变量” 

:Shell可以维护一些变量。变量中存放一些数据供以后使用。用户可以用”=”给变量赋值,如: 



         $lookup=/usr/mydir 



该命令建立一个名为lookup的变量并给其赋值/usr/mydir,以后用户可以在命令行中使用lookup来代替/usr/mydir,例如: 

          

         $echo $lookup 

         结果显示:/usr/mydir 



         为了使变量能被子进程使用,可用exprot命令,例如: 



         $lookup=/usr/mydir 

         $export lookup 



  ”运行环境控制” 

:当用户登陆启动shell后,shell要为用户创建一个工作的环境,如下: 



  1>当login程序激活用户shell后,将为用户建立环境变量。从/etc/profile和.profile文件中读出,在这些文件中一般都用$TERM 

变量设置终端类型,用$PATH变量设置Shell寻找可执行文件的路径。 



  2>从/etc/passwd文件或命令行启动shell时,用户可以给shell程序指定一些参数,例如”-x”,可以在命令执行前显示该命令及其参数。后面详细介绍这些参数。 



  ”shell编程” :本文主要介绍的内容。 



  shell本身也是一种语言(*可以先理解为unix命令的组合,加上类C的条件,循环等程序控制语句,类似dos批处理,但要强大的多),用户可以 

通过shell编程(脚本,文本文件),完成特定的工作。 



SHELL变量 



  下面我们详细的介绍Bourne Shell的编程: 



  自从贝尔实验室设计了Bourne 

Shell。从那时起许多厂商根据不同的硬件平台设计了许多版本得unix。但在众多版本的unix中,Bourne Shell 

一直保持一致。 

  1>Bsh的启动:用户在登陆后,系统根据文件/etc/passwd中有关该用户的信息项启动Shell。例如某用户在passwd中 

的信息项为: 



    ice_walk:!:411:103:Imsnow ,ice_walk:/home/ice_walk:/bin/bsh 



  则表明,用户名是ice_walk等信息,在最后一项”/bin/bsh”表明用户的sh环境类型是bsh,于是系统启动之。在启动或执行(包括下面我们要讲 

的shell程序–脚本)过程中可以使用以下一些参数,我们一一说明: 



  -a 将所有变量输出 

  -c “string”从string中读取命令 

  -e 使用非交互式模式 

  -f 禁止shell文件名产生 

  -h 定义 

  -i 交互式模式 

  -k 为命令的执行设置选项 

  -n 读取命令但不执行 

  -r 受限模式 

  -s 命令从标准输入读取 

  -t 执行一命令,然后退出shell 

  -u 在替换时,使用未设置的变量将会出错 

  -v 显示shell的输入行 

  -x 跟踪模式,显示执行的命令 



许多模式可以组合起来用,您可以试试了,但-ei好象不行,你说why呢? 



  使用set可以设置或取消shell的选项来改变shell环境。打开选项用”-“,关闭选项用”+”,多数unix允许打开或关闭a、f、e、h、k、n、 

u、v和x选项。若显示Shell中已经设置的选项,执行: 



    $echo $- 



  Bsh中每个用户的home目录下都有一个.profile文件,可以修改该文件来修改shell环境。为了增加一个可执行文件的路径(例如/ice_walk/bin), 

可以把下面代码加入.profile中 



    PATH=$PATH:/ice_walk/bin;exprot PATH 



   .profile中shell的环境变量意思如下: 



    CDPATH 执行cd命令时使用的搜索路径 

    HOME 用户的home目录 

    IFS 内部的域分割符,一般为空格符、制表符、或换行符 

    MAIL 指定特定文件(信箱)的路径,有UNIX邮件系统使用 

    PATH 寻找命令的搜索路径(同dos的config.sys的 path) 

    PS1 主命令提示符,默认是”$” 

    PS2 从命令提示符,默认是”>” 

    TERM 使用终端类型 



  2>Bsh里特殊字符及其含义 



  在Bsh中有一组非字母字符。这些字符的用途分为四类:作为特殊变量名、产生文件名、数据或程序控制以及引用和逃逸字符控制。他们 

可以让用户在Shell中使用最少的代码完成复杂的任务。 



     *> Shell变量名使用的特殊字符 

        $# 传送给命令Shell的参数序号 

        $- 在Shell启动或使用set命令时提供选项 

        $? 上一条命令执行后返回的值 

        $$ 当前shell的进程号 

        $! 上一个子进程的进程号 

        $@ 所有的参数,每个都用双括号括起 

        $* 所有参数,用双括号括起 

        $n 位置参数值,n表示位置 

        $0 当前shell名 

     *>产生文件名的特殊字符 

        包括”*”,”?”,”[]”,上面讲过,不再多说。 

     *>数据或程序控制使用的特殊字符 

        >(file) 输出重定向到文件中(没有文件则创建,有则覆盖) 

        >>(file) 

输出重定向到文件中(没有则创建,有则追加到文件尾部) 

        <(file) 输入重定向到文件 

        ; 命令分割符 

        | 管道符 

        & 后台运行(例如:sleep 10 &) 

        ` ` 命令替换,重定向一条命令的输出作为另一命令的参数 

     *>对于引用或逃逸的特殊字符 
继续阅读

发表在 Linux | 留下评论

ubuntu-14.04-server-amd64 允许root远程ssh登录

一 安装 ssh服务

apt-get install ssh

二 开通 root远程登录权限

vi /etc/ssh/sshd_config

将PermitRootLogin without-password 修改为PermitRootLogin yes

三 重启ssh服务

service ssh restart

继续阅读

发表在 Linux | 留下评论

mysql备份数据库

mysqldump -u root -p discuz > /mnt/discuz.sql  备份discuz数据库到 /mnt/discuz.sql 

或者mysqldump -u root -p discuz >/mnt/discuz.sql

恢复:mysql –u root -p discuz < /mnt/discuz.sql

继续阅读

发表在 Linux | 留下评论

CentOS安装编译环境

# yum install gcc gcc-c++ gcc-g77 flex bison autoconf automake bzip2-devel zlib-devel ncurses-devel libjpeg-devel libpng-devel libtiff-devel freetype-devel pam-devel openssl-devel libxml2-devel gettext-devel pcre-devel

果断把该装的组件一次性全部装了,以免编译时候出现错误。吼吼

继续阅读

发表在 Linux | 留下评论