I am LAZY bones? AN ancient AND boring SITE

分类: 'CLI软件' 的归档

记一下这个bash的http server

很久之前找到的小脚本,比较方便,可以基于此,自己在里面写各种逻辑,比如之前我是给改成做30x的跳转(根据输出参数,跳转到不同url),还是很合适的。
最近又想用,发现几乎找不到了,很多收藏的链接都已经失效了,于是觉得还是应该在自己能把控的地方记录下,把代码帖这个里吧,这个的效果和 python 的 SimpleHTTPServer 有点类似。
注意,这个脚本没有任何安全性可言,可以通过..访问到上级目录,也可能通过``执行任意指令,所以最好别长期开着。这只是个例子,处理逻辑自己改。

#!/usr/bin/env bash
while true
do
  f="/tmp/out$RANDOM"
  mkfifo "$f"
  trap "rm -f $f" EXIT
  cat "$f" | nc -4l 8000 > >(
    export REQUEST=
    while read -r line
    do
      line=$(echo "$line" | tr -d '\r\n')
      echo $line
      if echo "$line" | grep -qE '^GET /' ; then
        REQUEST=$(echo "$line" | cut -d ' ' -f2)
      elif [ -z "$line" ] ; then
        ( #这里面写自己的处理逻辑,这是一个很丑的例子。
        if [ "$REQUEST" == "/" ] ; then
          Message_Body="<!DOCTYPE html><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8></head><body>
`find . -type f -exec ls -l {} \; | awk '{print $1,$2,$3,$4,$5,$6,$7,$8,"<a href=\\"/" $9 "\\">" $9 "</a><br>"}'`</body></html>"
        else
          Message_Body="`cat "./$REQUEST"`"
        fi
        echo -en "HTTP/1.0 200 OK\nContent-Length: ${#Message_Body}\n\n$Message_Body"
        ) > "$f"
     fi
    done
  )
  rm -f "$f"
  echo done, next request.
done

另外,也可以看看几年前的这篇

一个dump DVD到mp4的脚本

注意:此脚本只是一个对我来说刚刚够用的脚本,并不是一个通用的方案,如果你的源DVD里有多语言、多字幕之类的,很可能需要修改参数才能正常运行,另外输出文件的码率、画面长宽、声音采样率等,也需要按实际情况修改。

给儿子买了12张巧虎的DVD,但是这年头,已经很少见DVD播放器了,电视机都是直接插U盘的,所以打算把DVD里的内容dump到U盘里(mp4格式),再进行播放。我的盘是按故事分段的,所以我也按段分成不同的mp4文件,一个盘的内容放在一个目录里。

用到的几个命令:

  • lsdvd命令可以取得DVD的标题、语言、字幕、分段等信息。
  • mencoder是个强大得一塌糊涂的视频/音频编码工具。
  • eject命令可以弹出光盘,放在脚本最后最合适了。

上脚本:

#!/bin/sh
 
DIR="/media/sda1/qiaohu"
DVD=`lsdvd`
title="`echo "$DVD" | grep "^Disc Title:" | cut -d ":" -f2-`"
title=${title:1}
chapters="`echo "$DVD" | grep "^Title" | awk -F"[ ,]+" '{print $6}'`"
echo "$title | $chapters"
T="$DIR/$title"
if [ -d "$T" ] ; then
	i=1
	while [ -d "$T$i" ] ; do
		((i++))
	done
	T="$T$i"
fi
mkdir "$T"
i=1
while [ $i -le $chapters ] ; do
	echo $T/$i.mp4
	mencoder -of lavf -lavfopts format=mp4 -oac lavc -ovc lavc -lavcopts aglobal=1:vglobal=1:vcodec=mpeg4:vbitrate=800:acodec=libfaac:abitrate=96 -af lavcresample=48000 -vf dsize=720:540:0,scale=0:0,expand=720:540,harddup -ofps 29.970 -srate 48000 -o "$T/$i.mp4" dvd://1 -chapter $i-$i
	((i++))
done
 
eject

突然又觉得这事儿挺折腾的,呵呵,而且不知道这样做(自己dump、自己看)算不算侵犯版权呢?

其实,文件也可以truncate

现在觉得,时间的流逝速度和年龄确实是成正比的。也就是说,年纪越大,就会觉得空闲时间越来越少了~
因此,本blog都大半个月没更新了,呵呵。也不能老这么沉寂下去,今天来写点东西。

熟悉数据库的朋友们都知道,大多数数据库都有个truncate指令:truncate table xxx可以把xxx表里的所有数据都删掉,但是保留表结构。其实,在有任何数据库之前,UNIX系统里就有了truncate这个命令了,当然后面的*nix里都保留了这个。可以想像,系统里的truncate命令的操作对象肯定是文件,而且此命令不仅能把文件的数据删成0字节,还可以缩减(甚至扩大)文件至指定的大小(通过 -s 选项指定文件大小值),这对于那种日志头部有些不想删除的关键信息,但后面的部分又很多很杂的情况下很有用。对于普通的日志文件,我们要清理的时候通常可以执行 > log 来清除文件的内容(这样,log文件会变成0字节),但是如果清理的同时想保留原始日志的前面4K的信息,不用truncate就会很麻烦了。

truncate的用法还是通过实战来解释吧,如下:

lily@LLY ~$ echo -n 1234567 > txt
lily@LLY ~$ cat txt
1234567lily@LLY ~$ 
lily@LLY ~$ truncate -s 4 txt
lily@LLY ~$ cat txt
1234lily@LLY ~$ 
lily@LLY ~$ ls -l txt
-rw-r--r-- 1 lily lily 4 1024 16:54 txt
lily@LLY ~$ truncate -s 1M txt
lily@LLY ~$ ls -l txt
-rw-r--r-- 1 lily lily 1048576 1024 17:17 txt
lily@LLY ~$ du txt
4	txt
lily@LLY ~$ wc -c txt
1048576 txt

这里还可以看到一个“奇怪”的现象,本来已经缩至4字节的文件,把它扩展成1M以后,ls 和 wc 的结果显示大小确实是1M,但是 du 的结果却发现大小还是4字节。这也是要注意的地方之一,这种文件称为“空洞文件”,也就是说,文件的部分内容并没有实际存在于硬盘上(即没有分配对应的inode),只是“声称”有1M的大小而已。对于不存在于硬盘上的那部分字节,如果去读的话,也是不会报错的,会读到全0的数据。
这也从另一个方面反映出ls等命令默认显示的是文件“声称”的大小,而du (disk use)默认显示的是真正的磁盘占用。这里是我以前的另外一个例子。

Common Internet File System

Common Internet File System 是samba的一部分,用于取代 smbfs 来挂载windows的共享文件夹,cifs比smbfs应用更广。
要使用 Common Internet File System 需要linux内核开启 cifs 支持。具体是要打开 File systems —> Network File Systems —> CIFS support (advanced network filesystem, SMBFS successor) 这个选项。如果是模块的话,使用前确保加载了。
然后,挂载共享文件夹,可以用mount命令的 -t cifs 选项来调用 mount.cifs。具体是:

sudo mount -t cifs //机器名或IP/远程/目录/ 本地挂载点 -o user=域/用户名%密码,iocharset=utf8

当然,没有域的话,也可以省略域。如果要指定其他mount的选项也是可以的,比如指定uid和gid之类的,这里就不多说了。

另外,如果gnome-base/gvfs开启了samba支持的话,也可以在nautilus的地址栏里直接输入 smb://机器名或IP/远程/目录/ 来打开远程目录,有密码时会弹出对话框输入。
这两种方法各有各的好处。

cryptsetup – 分区加密工具

cryptsetup是linux下的一个分区加密工具,和之前介绍过的eCryptfs不同的是:eCryptfs是文件系统级别的加密,而cryptsetup是分区级别的,比文件系统级别工作在更底层的位置,是在经过加密的块设备上,再创建文件系统,再挂载使用。这应该是纯软件能达到的最底层的加密了吧。
我折腾这玩意,是因为上篇文章说到,我要把/home的数据备份到另一个硬盘,而那个硬盘的物理安全性并不能得到充分地保证,所以只有通过加密来确保数据的安全了。如果当年陈老师也用这玩意的话,想必不会捅出这么大的篓子,呵呵。

废话不说,简单说说安装和使用的方法。
如果你是用ubuntu这类发行版的话,安装部分就很简单了,基本就是直接安装cryptsetup这个包,就完事了。
但是如果你和我一样也是用自己编译内核的发行版,比如gentoo的话,使用中可能会出现以下错误:

/proc/misc: No entry for device-mapper found
Is device-mapper driver missing from kernel?
Failure to communicate with kernel device-mapper driver.
Cannot initialize device-mapper. Is dm_mod kernel module loaded?
Command failed with code 22: Cannot initialize device-mapper. Is dm_mod kernel module loaded?

这时候你不要急着去安装 device-mapper ,因为现在 device-mapper 已经并入到更强大的 lvm2 里面了,所以你要确保装了 lvm2 和在内核选项里选择了CONFIG_DM_CRYPT,如下:

-> Device Drivers
  -> Multiple devices driver support
    -> Device mapper support
      -> Crypt target support

另外,还建议选取大文件支持的CONFIG_LBDAF和CONFIG_CRYPTO_AES两个内核选项,我这边不选取前者,会无法打开加密分区(虽然说LBDAF是2T+的单文件支持,而我的硬盘一共只有80G);后者是一个内核里的加密算法API,我们就用这个算法来加密(也可以用其他的算法)。

说说怎么使用:
建立一个加密的分区,很简单,执行下面的命令:

sudo cryptsetup --verbose --verify-passphrase -c aes-cbc-plain luksFormat /dev/sdb1

我的外接硬盘在 /dev/sdb1 ,因为这个命令会摧毁这个分区的所有数据,所以程序会让你确认,输入大写的YES,回车,就会让你输入两次密码,输完就搞定了。
话外音:其实cryptsetup不仅支持用密码加密,还支持用文件来加密,可以是任意类型的文件,不过解密的时候,要确保文件一个字节都不差,用这个特性可以方便地构建解密U盘。

好了,加密完分区以后,要使用的话,可以这样:

sudo cryptsetup luksOpen /dev/sdb1 back

其中最后的“back”,可以是任意字符串,程序会提示输入之前设置的密码,输对密码以后,文件系统里就会多出一个 /dev/mapper/back ,接下来就可以像使用 /dev/sdXX 一样地使用这个 /dev/mapper/back 了。
比如,建立一个ext4文件系统,挂载,复制文件之类:

sudo mkfs.ext4 /dev/mapper/back
sudo mount /dev/mapper/back /mnt/back/
sudo cp XXX /mnt/back/
....

使用完以后,可以这样显式地关闭加密分区:

sudo cryptsetup luksClose /dev/mapper/back

看看如果别人偷你加密后的硬盘,想挂载看你的艳照时,会怎么样?哈哈:

$ sudo mount /dev/sdb1 /mnt/back/
mount: unknown filesystem type 'crypto_LUKS'

PS: 现在ubuntu的易用性确实越来越好了,ubuntu里插入加密的硬盘后会自动判断,并直接弹出输入密码的窗口,输完自动挂载分区。

linux下的“虚拟光驱”

每当有人问我“你的linux下有没有类似‘虚拟光驱’的软件呢?”的时候,我就会轻轻一笑,自豪地说“别把事情想得太复杂,linux下根本就不用什么另外的软件,就能虚拟光驱了。”,然后那人一般就会似懂非懂地说一句:“哦。。这样啊~”
下面,就来介绍几个虚拟光驱相关的命令:
把物理光盘做成iso镜像,下面几个命令几乎等效,假设设备是/dev/cdrom:

cp /dev/cdrom xxx.iso
dd if=/dev/cdrom of=xxx.iso
mkisofs -r -o xxx.iso /dev/cdrom
readcd -v dev=/dev/cdrom -f xxx.iso

其中,用mkisofs还可以把一个文件夹模拟成iso:

mkisofs -o xxx.iso /path/to/tree

如果要使用iso文件的话,就更简单了,可以mount到任意目录下:

mount -o loop xxx.iso /path

注意以上某些命令可能需要root权限。

不过,还有个终极问题没有解决,我手头有一张《浙江省汽车驾驶人理科考试智能》的光盘,估计是用了什么防拷贝技术,使用以上方法都无法正确生成ISO文件,也无法全部复制里面的内容,具体操作过程如下:

lily@LLY:~$ sudo mount -o ro,loop /dev/sr0 qc
lily@LLY:~$ ls qc
试题10.db  试题11.db  试题12.db  试题1.db  试题2.db  试题3.db  试题4.db  试题5.db  试题6.db  试题7.db  试题8.db  试题9.db
lily@LLY:~$ sudo umount qc
lily@LLY:~$ sudo mount -o ro /dev/sr0 qc
lily@LLY:~$ ls qc
2009理论模拟考试.exe  AutoRun.ico  AutoRun.rdt  system               试题10.db  试题1.db  试题4.db  试题7.db
AutoRun.ard           autorun.inf  htm          安装使用说明.html    试题11.db  试题2.db  试题5.db  试题8.db
AutoRun.exe           autorun.pro  image.jpg    读安装使用说明.html  试题12.db  试题3.db  试题6.db  试题9.db
lily@LLY:~$ cp -r qc qc1
cp: 正在读入"qc/试题3.db": 输入/输出错误
cp: 正在读入"qc/试题4.db": 输入/输出错误
{1}lily@LLY:~$ ls qc1
2009理论模拟考试.exe  AutoRun.ico  AutoRun.rdt  system               试题10.db  试题1.db  试题4.db  试题7.db
AutoRun.ard           autorun.inf  htm          安装使用说明.html    试题11.db  试题2.db  试题5.db  试题8.db
AutoRun.exe           autorun.pro  image.jpg    读安装使用说明.html  试题12.db  试题3.db  试题6.db  试题9.db
lily@LLY:~$ du -s qc qc1
398463	qc
349720	qc1

有谁知道这种变态的光盘怎么搞定吗?

a2p──将awk程序转成perl

呵呵,不管你觉得有没有必要,反正,就是有这样的工具了,而且还是perl包自带的哦(看来perl确实有点怪异,哈哈)。
别的不说了,拿个小程序演示下,下面的awk程序是用来统计当前登录系统的人数的,其实就是 who | wc -l

BEGIN { 
while ( "who" | getline ) n++ 
print n 
}

然后这样:

lily@LLY:~/test/awk$ awk -f count.awk
3
lily@LLY:~/test/awk$ a2p count.awk > count.pl 
lily@LLY:~/test/awk$ perl count.pl
3

哈哈,确实能执行哦,再让我们来看看转出来的perl程序,格式都还蛮工整的呢:

#!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if $running_under_some_shell;
			# this emulates #! processing on NIH machines.
			# (remove #! line above if indigestible)
 
eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
			# process any FOO=bar switches
 
open(WHO_FH, 'who|') || die 'Cannot pipe from "who".';
 
$, = ' ';		# set output field separator
$\ = "\n";		# set output record separator
 
while (($_ = &Getline2('WHO_FH', '|'),$getline_ok)) {
    $n++;
}
print $n;
 
sub Getline2 {
    ($fh) = @_;
    if ($getline_ok = (($_ = <$fh>) ne '')) {
	;
    }
    $_;
}

想学perl的同学可以折腾折腾。

exif──查看JPEG文件里的附加信息

不知道什么是EXIF的可以看这里(中文)和这里(英文),简单一句话,EXIF就是存在JPG文件里的一些额外信息。
现在的数码相机拍出来的图片里,绝大多数都存有拍摄时间、快门、焦距、光圈等很多信息,稍微好点的还有GPS定位的拍摄地点呢。
在GUI下,eog等图片查看软件,都可以通过右键的“属性”菜单查看具体的EXIF信息。其实在CLI下,也是有办法提起这些信息的。这个程序的名字就叫 exif 。
安装基本靠源,就不介绍了,使用也是超简单:

$ exif S7302998.JPG
‘S7302998.JPG’中的EXIF 信息标识(‘英特尔’字节顺序):
--------------------+----------------------------------------------------------
信息标识                |值
--------------------+----------------------------------------------------------
Image Description   |<Samsung D70 / D75 / S730 / S750>
Manufacturer        |Samsung Techwin
Model               |<Samsung D70 / D75 / S730 / S750>
Orientation         |左上
x-Resolution        |96.00
y-Resolution        |96.00
Resolution Unit     |英寸
Software            |708101
Date and Time       |2009:02:08 14:16:22
###限于篇幅,省略点输出信息。。
对比度                 |普通
饱和度                 |普通
锐度                  |普通
Interoperability Ind|R98
Interoperability Ver|0100
--------------------+----------------------------------------------------------
EXIF 数据中含有缩略图(3915 个字节)。

下一步就是找个写EXIF信息功能强一点的CLI软件,exif虽然也能写,但是好像只能逐字段挨个写,这个就不太方便了。
最终我要实现的就是:压缩照片,但是保留EXIF信息,哈哈。

========20100211 19:30:00 update========
哈哈,是我把convert想得太简单了,其实convert本身就会保留EXIF的,根本无须我多操心~

自动化下载网盘的文件

今天,我给大家介绍两款自动化的网盘下载工具,用于自动下载MegauploadRapidshare等网盘的文件。

首先是有图形界面的FreeRapid,这是采用java编写的,所以可以跨平台使用,而且有比较良好的图形界面和多语言支持,改下设置,就可以出来中文界面,所以使用非常方便,也很容易上手,适合普通用户使用。
而且,FreeRapid还有个好处是支持的网盘网站非常的多,国外的大大小小的网盘站点几乎都能搞定。对各网站的支持还是以插件的形式出现的,也就是说,即使你的网盘站点的下载方式有变化,或者有新的网盘站点出现,FreeRapid也能很轻松地升级,以适应这个变化。事实上,在使用FreeRapid的过程中,也确实经常会看到有插件要更新的。

好了,大致说完了FreeRapid,这个的优点,刚说了,就是易用,因为有GUI嘛,不过,某些时候这样正是它的缺点所在(哲学中,矛盾性的普遍性得到了很好的验证,哈哈。),如果我的机器没有X怎么办呢?呵呵,不用着急,我们还有Plowshare
Plowshare已经默认包含在了gentoo或者arch的官方源里了,可以直接emerge或者yaourt,但是ubuntu源里,却还未包含,所以使用ubuntu的朋友需要自己下载deb包或者源码进行安装了。
这个的Plowshare比起FreeRapid来,支持的站点稍微少些,不过人家是bash脚本,不用拖个jre也不用X,还是很不错的,而且,它不止支持下载,其实还是支持上传的,哈。
使用起来也不烦,一般情况下只需要

plowdown URL

就好了,更详细的使用说明──比如支持某些站点的用户名、密码之类的──可以看官方说明
再说一句,这个也是模块化支持多站点的哦,而且作者还提供API,鼓励大家都去写模块呢。

怎么样,方便吧?

开源的命令行OCR软件──tesseract

tesseract-ocr是一个跨平台开源的OCR软件(Optical Character Recognition,光学字符识别),它历史悠久,早期是HP实验室的项目,现托管于google code。
大部分常用的linux发行版,应该都在源里包含了此软件,所以ubuntu下只需要 sudo apt-get install tesseract-ocr tesseract-ocr-eng 就可以安装了,注意必须安装 tesseract-ocr-eng 这个是识别英文字符所必须的数据文件。而在gentoo下,也只需要 emerge app-text/tesseract 就可以了,但是也必须给这个包添加 linguas_en 这个use,才会安装所需要的数据文件。
关于数据文件,还得交代一下,其实tesseract在2.0版以后,已经有了学习能力了,如果你想提高某个字体的识别率,或者识别不在默认语言包里的UTF-8字符(比如中文)的话,可以安装这个方法来训练出自己的数据文件。
这个OCR软件能干嘛呢?典型地应用就是识别验证码,哈哈。所以以这个为例,来介绍一下使用方法,先来看看这几个验证码(可“图片另存为”,然后自行测试):

这几个都是用默认的数据文件能正确识别的例子,由于tesseract只识别tiff格式的图片文件,所以识别之前,需要将图片先转成tif格式,具体如下:

$ convert cnblogs.com.jpe ppm:- | ppm2tiff yzm.tif
$ tesseract yzm.tif out
Tesseract Open Source OCR Engine
$ cat out.txt 
1750

同时,也有些比较难的验证码,是程序不能正确识别的,如下几个就是例子:

虽然识别的正确性不是非常高,但是已经很不错了,哈哈。
PS: 有没有人训练个识别google验证码专用的数据文件?