UMBR(Universal Master Boot Record),是一个简单的通用型的MBR引导程序,只支持LBA模式(BIOS不支持LBA的无法使用,目前除了很老的机子大部份都有支持).
使用创新的方案,和磁盘分区格式无关所以可以安装到MBR或GPT分区格式下,目前GPT磁盘一般都是配合EFI来启动,有了它就可以在BIOS模式下直接启动GPT磁盘上的系统(需要系统有支持)了.
目前该程序只能在GRUB4DOS环境下运行,请在最新版本GRUB4DOS环境下使用.
参数介绍:
umbr [-d=D] [-p=P] [--test] [file1] [file2] [file3]
-d=D 指定要安装的磁盘默认是当前ROOT的磁盘
-p=D 启动失败后要启动的分区默认是第一个分区.
--test 测试模式,不写入磁盘,加这个参数会进入安装效果测试.
file1-3 可以指定三个启动文件位置以防止启动失败.
注: 这个filex 可以是任意GRUB4DOS可以识别的文件格式(必须连续存放).比如(hdx,y)/path/file或(hdx)xxxx+yyyy/(hdx,y)xxx+yyy之类的.
file1-file3 必须在同一磁盘上并且和-d指定的磁盘一致.
file1-2 也可以是一是一个PBR比如(hd0,3)+1
file1是主启动文件,如果检验失败了会再尝试file2...
说明:
一个实用的例子:
磁盘使用的是GPT格式,GRLDR有两个备份分别是ESP分区(hd0,0)/grldr和普通分区(hd0,3)/boot/grub/grldr,并且在分区间隙(hd0)6554433+63处有一个WEE63
装有系统的分区是(hd0,1)
这时就可以通过UMBR默认加载ESP分区的GRLDR或普通分区上的GRLDR,失败了再尝试WEE63,还是失败就直接启动(hd0,1)分区.
进入GRUB4DOS执行以下命令就可以了
umbr -d=0 -p=1 (hd0,3)/boot/grub/grldr (hd0,0)/grldr (hd0)6554433+63
也可以默认wee63,通过wee63来控制启动过程,因为本例wee63是写到分区间隙的,出问题的几率比较小
umbr -d=0 -p=1 (hd0)6554433+63 (hd0,3)/boot/grub/grldr (hd0,0)/grldr
当然了也可以直接启动指定分区而不通过其它引导程序,如下默认直接启动(hd0,1)上的系统,如果该分区被分区软件调整过启动失败了,会尝试启动wee,最后尝试启动grldr
umbr -d=0 -p=1 (hd0,1)+1 (hd0)6554433+63 (hd0,0)/grldr
UMBR 相关说明
0x8 4个字节 UMBR标志
0xC 1个字节 UMBR版本号
0x10-0X3F 48个字节 用户定义的启动区
0x40-0X4F 16个字节 保留的启动区(当用户定义的启动都失败时启动的分区)
0x40-0x1B7 启动代码.
启动区说明,目前0x10-0x4F,每一个启动项占用16个字节,为了编程方便使用的是和DiskAddressPacket一样的格式.
WORD CRC; //启动项校验
WORD BlockCount; // 启动代码块数(以扇区为单位)
DWORD BufferAddr; // 传输缓冲地址(segment:offset),也就是启动地址
QWORD BlockNum; // 启动代码在磁盘上的位置(LBA)
BufferAddr 的值为0x07c00000(07c0:0000)时固定为PBR引导,启动时会自动修改0x7c1c处的值.其它值直接从该位置启动.
校验方法: 使用的是简单的XOR校验,最多校验127个扇区,按4个字节依次XOR得到的最后结果,再把低16位和高16位进行一次XOR得到最后的结果作为检验值.
具体的校验代码可以参考源码有ASM/C语言两个版本.
UMBR(Universal Master Boot Record),是一个简单的通用型的MBR引导程序,只支持LBA模式(BIOS不支持LBA的无法使用,目前除了很老的机子大部份都有支持).
使用创新的方案,和磁盘分区格式无关所以可以安装到MBR或GPT分区格式下,目前GPT磁盘一般都是配合EFI来启动,有了它就可以在BIOS模式下直接启动GPT磁盘上的系统(需要系统有支持)了.
]]>使用WIMBOOT可以节省大量的磁盘空间,特别是多系统的情况下更是明显.另外还具有WIM
文件的特性,比如增量备份,如果每隔一段时间就使用增量更新一下WIM那以后就可以随时恢复到每个更新点的状态.
正常安装的话一个64位的系统就差不多需要40GB了,我现在两个系统最多也才40GB,是不是很心动呢!
首先来秀一下最终的文件列表,很简洁.两个系统最多才占用40GB的空间.我使用用一个60G的固态硬盘.启动速度飞快.7秒左右进桌面
另外这两个系统还是打完了所有补丁再安装了所有需要的常用软件的,还包括了好几个G的VS2012,因为WIM文件相同的文件只会占用一个空间,所以我两个系统的所有的软件都装C盘.
注: 这个40G
是指最多会占用空间,实际上只使用了15G
左右,考虑到以后要安装软件还有更新什么的,64位保留15G,32位保留10G.
注:1. 以下只是我的系统情况演示,只供参考
2. 2015-05-01 感觉差分VHD是不必要的,以后更新的话只要更新主VHD就行了。并且由于我的内存有8G所以重新制作了一下,增加了一个5G的内存系统(win7.ram)。
有三个系统,并且以后可以随时增加
1. win7 x86 wimboot ==>x86\win7.vhd
2. win7 x86 wimboot(内存模式) ==>x86\win7.ram
3. win7 x64 wimboot ==>x64\win7.vhd
BOOTMGR ==>启动文件
wimboot.wim ==>和wimboot目录下的一样,只是为了方便更新系统
├─boot ==>启动文件目录
│ │ memtest.exe
│ │
│ ├─Fonts ==>启动界面字体
│ │ chs_boot.ttf
│ │ cht_boot.ttf
│ │ jpn_boot.ttf
│ │ kor_boot.ttf
│ │ wgl4_boot.ttf
│ │
│ │
│ └─zh-CN
│ bootmgr.exe.mui
│ memtest.exe.mui
│
└─wimboot ==>系统文件夹
│ wimboot.wim ==>系统WIM WINDOWS 7 x86/x64二合一镜像 占用14G空间
│
├─x64 ==>64位系统
│ win7.vhd ==>64位系统主15G VHD文件 ==>使用非固实模式只占用400MB左右
│
└─x86 ==>32位系统
Win7.vhd ==>32位系统主10G VHD文件 ==>使用非固实模式只占用400MB左右
Win7.ram ==>32位系统RAM模式镜像40MB(使用grub4dos map --mem --top来启动)
再来一张截图对比(整个系统有16G实际只占用了703MB的空间)
看了上面的简单介绍是不是很心动,也想自己改造一个呢?别急慢慢来.
WIMBOOT
WIMBoot是Windows image file boot的简称,是Windows 8.1 的一项新型启动方式。这种启动方式让电脑从一个高度压缩的文件启动,大大减少了磁盘空间的占有,还具有快速升级、快速恢复出厂设置等优点.
WIMBOOT
方式启动WINDOWS 7 使用WIMBOOT的方法在网上论坛上有很多介绍,不过太部份操作起来都比较复杂,经过我的改造,现在简化了一些步骤,现在不需要任何输入,一键就可以实现了。
功能:
提示:
Win_系统版本_日期时间
,例子: Win_6.1_201505101200 2015-09-07 v2.5版
1. BUG修正.
2. 支持自定义实体化文件列表(同目录下的WimbootExtract.ini)
2015-07-27 v2.4版
1. BUG修正.
2015-07-17 v2.3版
1. 驱动更新到10240版,服务改为wofadk.
2. 修正局域网打印机安装问题和浏览器DLL错误问题(感谢无论[2012liujingxion](http://bbs.wuyou.net/forum.php?mod=viewthread&tid=367490))
3. BUG修正.
2015-06-29 v2.2版
1. 修正增量更新的一个BUG。
2. 自适合DPI
2015-06-28 v2.1版
1. BUG修正.
2. Add English Language
2015-06-18 v2.0版
1. BUG修正(长路径名恢复失败).
2. 界面调整,改成了使用进度条(之前是直接显示WIMLIB执行的所有信息)
3. 添加压缩率选项.
2015-06-17 v1.9版
1. BUG修正.
2. 盘符重置功能修改,增加自动判断.
2015-06-16 v1.8版
1. 修正一个BUG.
2. 驱动更新,解决NTFS软硬链接的问题.(已经有装过的,可以删除原系统drivers目录下的wof.sys文件,然后再使用增量更新或原地转换功能即可更新为最新版驱动)
2015-05-29 v1.7版
1. 支持修改WIM信息(wim info)(新版的E按钮)
2. 增加更多可选项,具体看后面的最新版截图
3. 修正上个版本在PE下多次执行出错的问题.
2015-05-22 v1.6版
1. 支持Windows 10
2. 增量备份支持单独存放(不合并)
3. 捕获或恢复时可以选择不使用WIMBoot.
4. 界面调整程序优化并增加一些操作提示信息。
5. 新的wimlib-imagex程序,支持显示中文镜像名称。
2015-05-18 v1.5版
1. 新增仅捕获选项
2. 新版本对于部份操作不再强制要求格式化。
3. 对于已经是WIMBOOT的系统,现在可以正确识别该系统所使用的WIM文件,并自动选择该WIM文件
4. BUG修正,界面调整。
2015-05-14 v1.4版
1. 再次修改NTFS分区识别错误的问题
2. 其它BUG修正
3. 支持拖放操作,基本参数框内可以拖放WIM文件或WimBootCompress.ini文件
4. 支持使用命令行修改默认的WIM文件存放目录, 格式如下:
WIMBoot.exe -WIMPATH:目录名
例子:使用WIMBOOT目录
WIMBoot.exe -WIMPATH:\WIMBOOT
2015-05-12 v1.3版
1. 修正部份PE检测Wof驱动失败的问题。
2. WIMBoot.exe同目录下有存在WimBootCompress.ini捕获时会自动使用该配置。
3. 几个小BUG修正,继续完善.
2015-05-11 v1.2版
1. 禁用精简捕获模式,只使用完整捕获模式。
2. 选择目标系统会自动判断是否已经是WIMBoot的,是的话会自动查找对应的WIM文件(目前不是很准确,先将就着).
2015-05-10 更新: v1.1 使用我自己修改编译的WIMLIB程序,现在终于实现一步到位的更新操作,不再需要SYSTEM权限,修复了上个版本的两个小BUG。
2015-05-09 更新: 现在可以直接在PE下一步到位进行转换或更新操作(更新操作需要SYSTEM权限或WIN8PE),并且支持WES7 64位
2015-04-21 第一版,使用了两个批处理脚本来实现,需要两步来实现。
注:最新版本已经更新了驱动,应该解决了该问题
[ERROR] "E:\MSOCache\All Users\{90150000-0011-0000-1000-0000000FF1CE}-C\OWOW32WW.cab": Error reading data (status=c000046e): %2 0x%1
ERROR: Exiting with error code 50:
Could not read data from a file.
出现上面错误的原因是由于在已经是WIMBOOT启动的目标系统上用了原地转换功能,这是不受支持的。
解决方法:
在PE中安装WOF驱动,或使用WIN8PE(一般会有带WOF驱动),再使用原地转换功能。
找到你之前的WIMBOOT.WIM复制一份到System Volume Information目录(你想存放WIM文件的磁盘分区下).再启动WIMBoot.exe,程序会自动检测到这个新的WIMBOOT.WIM并且可以使用增量更新功能,如果没有自动检测到,可以手工选择一下你的WIM文件存放磁盘。
最新V1.2会已经实现自动识别目标分区并且自动查找对应的WIM文件
[WARNING] Retrying after 100ms...
[WARNING] FSCTL_SET_EXTERNAL_BACKING failed (err=1314); data was 48 bytes:
0100000001000000010000000000000001000000000000008ccd4ce7b554c8f11c8a5fd5231de42e
d4085f6b00000000
[WARNING] Too many retries; returning failure
[ERROR] "f:\test\WIMBOOT\Readme.TXT": Couldn't set WIMBoot pointer data (err=131
4):
ERROR: Exiting with error code 75:
Failed to set WIMBoot pointer data.
注: v1.1以上版本出现以上问题,请选中格式化功能,在应用的时候格式化目标系统分区就可以解决该问题。
出现类似以上的错误提示说明需要SYSTEM权限,目前可以使用以下两种方法解决。
使用NSudo或psexec软件来获取SYSTEM权限,用SYSTEM权限运行WIMBOOT.EXE
或
直接重启系统进入PE运行WIMBOOT.EXE使用系统恢复功能进行恢复最新的镜像就行了。
以上是旧版本才会出现的问题,如果使用V1.1版本也有这些问题请留言回复
这是正常的,因为使用WIMBoot大部份的系统文件其实只是一个指向WIM文件的指针,需要安装WOF驱动才可以正常访问,另外程序在应用之前也会禁用该分区的Wof所以即使是已经安装了wof驱动应用之后也是不能直接访问的,重启系统只要有WOF驱动就可以正常访问。
如果在WIMBoot启动的,那在系统盘的System Volume Information目录下有一个文件WimOverlay.dat,这个文件记录了对应WIM文件的位置信息,如果目标WIM文件在MBR磁盘上,则记录了分区偏移和磁盘签名信息,若是GPT磁盘记则记录分区GUID和磁盘GUID
我编写了一个小程序(自己提取资源 EXEDATA#1023),你可以通过它来快速读取这些信息,例子:
fwim c:\System Volume Information\WimOverlay.dat
168 32768 661951F1
第一个数字168是WIM文件路径在文件中的位置,可以通过PECMD的GETF来读取完整路径信息
GETF# x:\System Volume Information\WimOverlay.dat,168#*,SYSWIM
然后再通过分区偏移和磁盘签名等信息就可以获取到对应的盘符,以下是相关代码
_SUB GetALLPartInfo
PART list disk,&&全部磁盘
forx * %全部磁盘%,&磁盘,
{
PART list disk %磁盘%,&&磁盘信息
MSTR * &磁盘签名=<8>&&磁盘信息
PART list part %磁盘%,&&全部分区
forx * %全部分区%,&分区,
{
IFEX #%&分区%<0,EXIT CONTINUE
PART -hextp -phy# -fill list part %磁盘%#%分区%,&&分区信息
SED &&GPT=?,GPT,,%&&分区信息%
IFEX #%GPT%>0,MSTR * &&偏移,&&盘符,&&DN=<-3><-1><-2>&&分区信息 ! MSTR * &&偏移,&&盘符,&&DN=<4><-1><-2>&&分区信息
SET. 所有分区=%所有分区%%盘符% %偏移% %&磁盘签名% \Device\Harddisk%磁盘%\Partition%&&DN%\n
}
}
_END
SET-def 所有分区=
CALL GetALLPartInfo
EXEC* &&N=!fwim "c:\System Volume Information\WimOverlay.dat"
CALL GetWoCf c: %&&N%
_SUB GetWoCf
IFEX #%2<0,EXIT _SUB
ENVI &P=
FORX *NL &所有分区,&T,
{
SED &&a=?,%3 %4,,%T%
IFEX #%&&a%>0,
{
LSTR &P=2,%T%
FIND $%&P%=*,
{
//对应的分区未分配盘符,临时分配一个@:
SUBJ &- @:
MSTR$ * &p=<-1>T
SUBJ & @:,%&P%
ENVI &P=@:
}
EXIT FORX
}
}
GETF# %1\System Volume Information\WimOverlay.dat,%2#*,SYSWIM
ENVI SYSWIM=%&p%%SYSWIM%
_END
增量更新功能
系统恢复功能
首次使用的情况
界面和相关介绍.
最新版本界面截图
需要准备的文件 下载: http://pan.baidu.com/s/1mgIbMyc 密码: 83qe
先创建wimboot目录列表,并复制wimboot.wim到wimboot目录下和根目录下(备用).
x64\win7.vhd
和x86\win7.vhd
并安装.一些需要注意的事项:
]]>文件名称: wimboot.wim
文件大小: 3.71 GB (3,979,257,171 字节)
修改时间: 2015年04月30日,23:47:38
MD5: 1A98B453AB3F516FAC5C084D85028F42
SHA1: DD3701475BF7F4C478A9A0A7AF485157EFB48BE7
使用WIMBOOT可以节省大量的磁盘空间,特别是多系统的情况下更是明显.另外还具有WIM
文件的特性,比如增量备份,如果每隔一段时间就使用增量更新一下WIM那以后就可以随时恢复到每个更新点的状态.
正常安装的话一个64位的系统就差不多需要40GB了,我现在两个系统最多也才40GB,是不是很心动呢!
]]>ipxegrldr
文件,这个文件其实是整合了undionly.kpxe
和grldr
的文件,可以作为PXE的启动文件.
ipxe
的所有功能调用,通过它允许直接在grub4dos
下访问WEB
或SAN
上面的文件.另外相对应的增加了一个命令ipxe
,使用它可以调用各种ipxe命令
ipxe 命令语法: ipxe [cmd] [params]
可以直接访问网络上的文件.
cat http://b.chenall.net/menu.ipxe
map --mem http://b.chenall.net/ntboot.iso (0xff)
map --hook
ls (0xff)
利用ipxe
命令来实现更多功能
使用ipxe命令时需要注意一点,最好在文本模式下运行(terminal console)运行ipxe,特别是像ipxe chain
或ipxe boot
之类的,否则会看不到ipxe的回显.看起来就像是假死状态.
可以直接调用ipxe的各种命令,例子
直接调用ipxe菜单(注:在ipxe菜单中可以用exit命令返回)
ipxe chain http://b.chenall.net/menu.ipxe
直接使用ipxe启动网络上的文件
ipxe chain http://b.chenall.net/grldr
直接使用ipxe启动网络上的镜像文件例子
ipxe sanboot http://b.chenall.net/ntboot.img
ipxe sanboot iscsi:10.0.4.1:::1:iqn.2010-04.org.ipxe.dolphin:storage
高级用法,通过sanhook来直接把网络上的镜像映射为一个本地设备.
sanhook 可以把映射一个网络镜像相当于grub4dos的map,只是这个是直接映射,读写都是通过网络完成的.
sanunhook 删除一个映射.
ipxe sanhook -d 0xff http://b.chenall.net/ntboot.iso
ipxe sanunhook -d 0xff
The format of an iSCSI SAN URI is defined by RFC 4173. The general syntax is:
iscsi:<servername>:<protocol>:<port>:<LUN>:<targetname>
For example:
iscsi:10.0.4.1:::1:iqn.2010-04.org.ipxe.dolphin:storage iscsi:boot.ipxe.org::::iqn.2010-04.org.ipxe.boot:public iscsi:192.168.0.1::::iqn.1991-05.com.microsoft:msdos622-target iscsi:opensolaris.home::::iqn.1986-03.com.sun:02:e9abf4cd-714b-c6ec-d017-eea5a56252ed
<servername>
is the DNS name or IP address of the iSCSI target.<protocol>
is ignored and can be left empty.1)<port>
is the TCP port of the iSCSI target. It can be left empty, in which case the default port (3260) will be used.<LUN>
is the SCSI LUN of the boot disk, in hexadecimal. It can be left empty, in which case the default LUN (0) will be used.<targetname>
is the iSCSI target IQN.If you are using iSCSI authentication, then you will need to configure the username and password settings (and possibly also the reverse-username and reverse-password settings) before attempting to connect to the SAN target. There is no way to specify usernames and passwords directly within the iSCSI SAN URI.
grub4dos下也可能直接通过ipxe来加载wimboot,但是有一些需要注意,否则会启动失败.
例子: 有一个boot.ipxe文件在服务器上
#!ipxe
imgfree
imgfree
imgfree
kernel wimboot
initrd boot/bcd BCD
initrd boot/boot.sdi boot.sdi
initrd boot/bootmgr bootmgr
initrd boot/boot.wim boot.wim
boot
注: 几个imgfree的命令是保证当前ipxe加载的镜像内容为空,也就是让使用imgstat命令显示的内容为空.
然后直接使用GRUB4DOS的ipxe命令加载
## terminal console 是必须的,切换到文本模式,否则启动可能会不显示(假死状态).
terminal console
## -a 参数也是必须的,自动释放boot.ipxe镜像,否则有可能会失败.
ipxe chain -a http://192.168.0.1/boot.ipxe
以上是ipxe的原生方法来启动wimboot,也可以使用grub4dos内置的用法(目前不稳定有时会导致重启).
title Wimboot
kernel /wimboot
initrd @bcd=/boot/bcd @bootmgr=/boot/bootmgr @boot.sdi=/boot/boot.sdi @boot.wim=/boot/boot.wim
boot
后记: 使用ipxegrldr
作为PXE启动文件还有另一个好处,就是如果网络正常的话,使用ipxegrldr
总是会优先使用 http://b.chenall.net/grldr 来启动,也就是说总是使用最新的版本.当然了如果网络不通的话就使用内置的版本.如果你不需要这个功能的话可以直接使用undionly.kpxe自己写菜单来启动grldr
ipxegrldr
文件,这个文件其实是整合了undionly.kpxe
和grldr
的文件,可以作为PXE的启动文件.
ipxe
的所有功能调用,通过它允许直接在grub4dos
下访问WEB
或SAN
上面的文件.另外相对应的增加了一个命令ipxe
,使用它可以调用各种ipxe命令
ipxe 命令语法: ipxe [cmd] [params]
]]>linux initramfs
,另外为了方便使用还支持了自定义的批处理续尾格式.这些在grub4dos被识别为initrdfs
,都是在内存中使用的.
目前grub4dos initrdfs文件系统仅支持cpio new
格式和grub4dos自定义格式,
批处理续尾格式支持整合多个批处理和一块非批处理的数据块.
主批处理[+批处理1][+批处理2][+批处理N][+数据块1]
除了主批处理程序之后其它附加的内容都可以在主批处理中直接访问.访问方法 %~m0/N
N是顺序号(注:当有附加了多个批处理时才可以这样子访问),详见后面更多介绍.
以下摘抄一些资料
initrd与initramfs
Linux 的
initrd
技术是一个非常普遍使用的机制,linux2.6 内核的 initrd 的文件格式由原来的文件系统镜像文件转变成了 cpio 格式,变化不仅反映在文件格式上, linux 内核对这两种格式的 initrd 的处理有着截然的不同。initrd:
ram disk是一个基于ram的块设备,因此它占据了一块固定的内存,而且事先要使用特定的工具比如mke2fs格式化,还需要一个文件系统驱动来读写其上的文件。
如果这个disk上的空间没有用完,这些未用的内存就浪费掉了,并且这个disk的空间固定导致容量有限,要想装入更多的文件就需要重新格式化。
由于Linux的块设备缓冲特性, ram disk上的数据被拷贝到page cache(对于文件数据)和dentry cache(对于目录项), 这个也导致内存浪费.initramfs:
最初的想法是Linus提出的: 把cache当作文件系统装载。
他在一个叫ramfs的cache实现上加了一层很薄的封装,其他内核开发人员编写了一个改进版tmpfs,这个文件系统上的数据可以写出到交换分区,而且可以设定一个tmpfs装载点的最大尺寸以免耗尽内存。initramfs就是tmpfs的一个应用。
优点:
- tmpfs随着其中数据的增减自动增减容量.
- 在tmpfs和page cache/dentry cache之间没有重复数据.
- tmpfs重复利用了Linux caching的代码, 因此几乎没有增加内核尺寸, 而caching的代码已经经过良好测试, 所以tmpfs的代码质量也有保证.
- 不需要额外的文件系统驱动.
另外,
initrd
机制被设计为旧的”root=”机制的前端,而非其替代物,它假设真正的根设备是一个块设备, 而且也假设了自己不是真正的根设备,这样不便将NFS等作为根文件系统。最后/linuxrc
不是以PID=1
执行的, 因为1
这个进程ID
是给/sbin/init
保留的。initrd
机制找到真正的根设备后将其设备号写入/proc/sys/kernel/real-root-dev, 然后控制转移到内核由其装载根文件系统并启动/sbin/init。initramfs
则去掉了上述假设, 而且/init
以PID=1
执行, 由init
装载根文件系统并用exec
转到真正的/sbin/init, 这样也导致一个更为干净漂亮的设计。生成initramfs镜像命令
若镜像根目录为/initrd,执行下面命令在当前用户主文件夹中生成myinitramfs.gz镜像。
cd /initrd find .|cpio -o -H newc|gzip>~/myinitramfs.gz
注1: 以上生成的镜像文件是gzip压缩过的。如果不加
|gzip
则就是原始的cpio档.
注2: windows下可以使用以下命令行成
dir /b | cpio -o -H newc > myinitramfs.cpio
NULL
字符分隔每个批处理(必须的,而且只能有一个NULL
字符),并且附加的批处理文件不能压缩(暂不支持压缩). 如果这个数据文件没有压缩,而且是GRUB4DOS可以识别的格式那可以直接用设备%~m0
来访问里面的文件.
建议只附加一个CPIO/ISO格式,这样子使用起来最方便,也最节省空间(附加的文件同样不要压缩).
批处理加附一个CPIO文件(CPIO里面的文件可以压缩)
则在批处理中可以直接使用%~m0/FILE
访问File
就是CPIO包里面对应的文件.
ISO/IMG等格式也是一样的.
访问方式: %~m0/0
是第一个文件,%~m0/1
是第二个文件,以此类推.并且可以直接运行
注: 只允许最多一个数据文件并且只能附加在最后面,中间只能附加批处理文件
根据附加顺序%~m0/0
%~m0/1
来访问
若附加的数据文件是CPIO等GRUB4DOS可识别的格式,而且没有压缩的话,那可以通过以下方法访问里面的文件
::本例子附加了一个批处理和一个数据文件(可以是cpio/iso/img等grub4dos可访问的文件系统格式)
set rdev=
::使用%~m0/1访问第二个文件(数据文件),通过blocklist命令获取该文件的扇区序列(或在内存中的位置)
::以下这一个命令获取指定文件在内存中的位置(md,X,Y)的格式保存在变量rdev中.
blocklist %~m0/1 | call :get_dev=
::现在可以直接访问这个rdev的内容.例子*ls (md,0x1600000,0x12000)/*这样的格式
ls %rdev%/
::查看内存设备`%rdev%`里面的文件`file`的内容.
cat %rdev%/file
goto :eof
:get_dev
set rdev=%~d1
goto :eof
]]>linux initramfs
,另外为了方便使用还支持了自定义的批处理续尾格式.这些在grub4dos被识别为initrdfs
,都是在内存中使用的.
目前grub4dos initrdfs文件系统仅支持cpio new
格式和grub4dos自定义格式,
批处理续尾格式支持整合多个批处理和一块非批处理的数据块.
主批处理[+批处理1][+批处理2][+批处理N][+数据块1]
除了主批处理程序之后其它附加的内容都可以在主批处理中直接访问.访问方法 %~m0/N
N是顺序号(注:当有附加了多个批处理时才可以这样子访问),详见后面更多介绍.
This application requires root(需要手机有Root权限)
DriveDroid allows you to boot your PC from ISO/IMG files stored on your phone. This is ideal for trying Linux distributions or always having a rescue-system on the go… without the need to burn different CDs or USB pendrives.
DriveDroid also includes a convenient download menu where you can download USB-images of a number of operating systems from your phone (like Mint, Ubuntu, Fedora, OpenSUSE and Arch Linux). Around 35 different systems are available at this moment.
You can also create blank USB-images which allows you to have a blank USB-drive. From your PC you can store files onto the USB-drive, but also use tools on your PC to write images to the drive.
More info: http://softwarebakery.com/projects/drivedroid
以上是原文介绍,看不懂没有关系,简单来说,就是可以让Root的Android设备可以直接加载ISO/IMG等文件直接变身为一个启动盘(可以变成U盘/光盘/软盘),系统安装盘,等,也就是说一个手机加上一条数据线就可作为随身或应急维护U盘了.
请先使用向导,根据界面提示获取ROOT权限,插入USB数据线
可以直接创建一个空白的IMG文件(虚拟U盘),挂载这个镜像文件之后,连上电脑之后就可以看到一个”空白的U盘”,你想怎么折腾就怎么折腾吧..
点击+
号出现如上菜单,第一个是创建空白镜像,第二个,从镜像库下载,第三个,从系统中加载已经做好的镜像.
软件还内置了一个镜像库,提供一些可以启动的镜像(比如Linux系统发行版)等,直接下载就可以使用了.
除了可以挂载IMG/ISO文件之后,还可以挂载整个SD卡/某个SD卡分区,系统分区的哦..看截图(要挂载这些需要对ANDROID/linux系统有一定的了解)
本人的手机对这个支持的效果挺不错的,可以有三个LUN,可以同时支持软盘、光盘、U盘。效果图,lun0虚拟出一个软盘,lun1是光盘,lun2是可移动磁盘
注意看上图,左边有三个点,代表该设备支持三个LUN,你可以在每个LUN上都测试挂载一下 光盘,软盘等镜像,看看电脑上能不能正确显示出挂载内容,这样就可以知道是否有支持虚拟光盘,软盘了.
挂载之后卸载的方法见图示,通过状态栏可以方便卸载某个虚拟设备
也可以直接使用该软件挂载系统设备比如系统的DATA分区/SYSTEM分区等.如上面的截图里面的设备,对Linux系统比较了解的朋友应该就懂得.在Android中每个设备在/dev
目录中都有一个对应的设备文件名,比如SD卡(在很多ANDROID设备中使用/dev/block/vold/179:27
),那我们是否可以在DriveDroid
中直接加载该文件来实现挂载直接SD卡设备呢?答案是可行的,不过因为系统的限制你并不能直接在软件中的直接选择添加,需要手工填写文件名称才行.
首先是要找到你想要添加的设备的文件名,一般情况下通过mount
命令就可以看到对应设备的挂载点.可以在adb shell
或android终端软件中输入如下图
注意看上面红色框的内容,本手机179:27
是sdcard0
(内置sd卡),179:65
是sdcard1
(外置SD卡)
好了找到了对应的设备文件名,现在就可以开始添加了.点软件右下角的+
号,选择Add image from file…开始添加,出现如下图界面,输入对应的信息然后点右上角的SAVE保存就行了.
具体效果可以看前面的介绍截图,另外挂载这设设备时,为了避免出现问题,最好使用只读挂载(Read Only),比如你可以只读挂载一下SYSTEM
分区,然后在Windows
下就可以备份这个分区的内容.
附: 更多可挂载的设备.
注: 除了使用/dev/block/vold/179:27
之外也可以使用/dev/block/mmcblk0p27
两个是一样的,具体可以看上面的图片
mmcblk0
是系统内置的储存设备使用时需要小心,mmcblk1
一般是外置的tf卡设备.mmcblkXpY
对应X储存的Y分区,比如mmcblk1p1
就是外置tf卡的第一个分区发现很多朋友认为使用软件会影响读写速度,如果你了解这个软件的原理就明白了,无非就是修改了android的默认宿主usb挂载点.
比如系统自带的U盘模式其实效果和用这个软件挂载整个SD卡是一样的.
用ISO之类的文件的话因为需要多一层读写,效率会低一点,但影响不是很大,关建是用ISO/IMG文件使用起来更方便.我觉得使用一点点的效率去换取这些更方便功能是值得的.
在没有发现这个软件之前,我通过手工修改Android的默认的usb挂载点来实现这些功能,使用软件需要使用工具就加载什么,还可以使用只读模式,防病毒最有效的就是只读模式了,很方便不是吗?
从Google Play 下载安装:(https://play.google.com/store/apps/details?id=com.softwarebakery.drivedroid&feature=nav_result)
百度网盘下载: com.softwarebakery.drivedroid.ver.0.9.15.build.46.apk
]]>This application requires root(需要手机有Root权限)
DriveDroid allows you to boot your PC from ISO/IMG files stored on your phone. This is ideal for trying Linux distributions or always having a rescue-system on the go… without the need to burn different CDs or USB pendrives.
DriveDroid also includes a convenient download menu where you can download USB-images of a number of operating systems from your phone (like Mint, Ubuntu, Fedora, OpenSUSE and Arch Linux). Around 35 different systems are available at this moment.
You can also create blank USB-images which allows you to have a blank USB-drive. From your PC you can store files onto the USB-drive, but also use tools on your PC to write images to the drive.
]]>
这里以 百度云管家绿色版 转换为Cameyo虚拟化包为例,因为这个相对比较简单,不需要更多设置,可以直接运行:
首先打开 PackageEditor 启动编辑器,创建新的虚拟程序包(本例用的是2.X的版本).到了如下界面,在这里可以进行一些基本的设置,像运行模式之类的,还有扩展属性(本例最终的设置效果在后面).
现在开始添加所有需要的文件进去.
添加完文件之后再设置一下主程序,如里有多个可以使用菜单.
使用更改图标功能设置应用的图标(会同时设置应用属性),直接在弹出的窗口中选择百度云管家的主程序就行了,,最终的设置效果图
现在把它保存起来.比如保存为 BaiduYunGuanjia 最终的文件名是 BaiduYunGuanjia.cameyo.exe,双击就可以直接启动百度云管家了.
看起来很简单,不是吗?
当然了以上是最基本也是比较简单的,为了方便直接使用了完全访问的模式,如果使用数据模式或其它模式,则还需要设置一下下载路径允许比如 D:\BaiduYunDownload 的文件系统访问模式为完全访问,请继续往下看.
上面的是完全访问模式,也就是说这个虚拟化包可以对系统文件进行修改之类的,不太安全,一般除非特殊情况,不建议使用该模式,比较常用的是数据模式.
下面简单介绍一下各种模式的区别:
首先关于虚拟文件/注册表系统的一些基本概念(以下都是相对真实系统而言):
Cameyo基本数据访问模式:
百度云管家只是用来管理百度网盘上的文件的,所以我这里设置为数据模式,由于下载的文件一般是存放在D盘的,所以同时允许对D盘完全访问.
这些设置在上面的第二张图片的界面上设置,选中目录,然后点击右上角系统文件旁边的选项进行修改.也可以下载本文附件用PackageEditor打开查看.
我制作好的百度云管家Cameyo单文件版下载: 百度云管家单文件绿色版
]]>Cameyo 是一款完全免费的应用程序虚拟化 (Application Virtualization) 工具或者说单文件软件制作工具,支持 XP、Vista 、 Windows7、Windows8,支持32位和64位系统。应用程序虚拟化技术就是将完整的程序资源打包为一个单一的可执行文件,从而无需安装即可运行。以前,要制作绿色软件需要学习很多技术,一般用户难以入门,而 Cameyo 则将此绿化过程变得简单且傻瓜。
Cameyo 的原理是利用沙盒(Sandbox)的虚拟化技术,先把所有相关资源打包成单个绿色文件,当执行这个“绿色软件”时,它会产生一个虚拟环境来执行,类似影子系统一样,一切涉及的操作都是在这个虚拟环境中完成,并不会去动原本的系统。所以使用 Cameyo 制作的绿色软件还有一个好处就是几乎不会对系统有害。
由于官方原版的翻译一直有问题,为了方便就自己修改编译一个,这个 PackageEditor 是基于官方源码,修改中文资源之后重新编译的,使用2.1版的源码主是要因为这个版本是个过渡版本,同时支持旧版和新的版本的编辑(只需要把不同版本的dll文件放进去就行了)。
使用新的版本可以很方便的创建新的虚拟化程序,默认使用的是快照的方式(获取快照->安装软件->获取快照->对比生成虚拟化包).
使用快照生成虚拟化包的方法:
上面的方法生成的应用程序会较完整通用,还有另一个方法,速度比较快,但是很多程序不支持..
进入命令行,执行以下命令,然后正常安装就行了.
PackageEditor.exe -exec #2 -GhostCapture 安装程序
比如某个应用程序的安装文件Setup.exe在d:下
PackageEditor.exe -exec #2 -GhostCapture d:\Setup.exe
修改SDK API实现二合一,新的编辑器同时支持编辑新旧两种虚拟化包格式,会自动判断,若是打开的是旧版格式,会提示是否升级,不升级就保留旧版格式.另外使用这个编辑器创建新的虚拟化包时只能创建为旧版格式.需要用新格式的可以保存之后重新打开在提示转换是选择是就行了.
顺便说一下新旧格式的区别: 新版主要是支持内存运行模式,还有支持用户数据分离等特性,因为使用了新的压缩格式,速度会快一些,缺点就是产生的虚拟化程序会比较大.另外旧版可以直接用7Z打开看到里面的文件,新版的不行.
2.1版修改内容:
2.6版只是修改了简体中文资源文件.
普通用户的设置界面和前面的一样的,下图有多一些设置界面,这些是需要授权的
授权申请网址: http://www.cameyo.com/upgrade
里面有版本对比和升级申请,有需要的可以自己去申请,不一定能通过.
不再更新 == 2.1编辑器+2.0版核心: PackageEditor2.1简体中文版(内置2.0版组件)
不再更新 == 2.6编辑器(内存模式运行): PackageEditor2.6简体中文版
最新2.6增强版(推荐使用): PackageEditor 2.6增强版
Cameyo 官方文档(英文): http://www.cameyo.com/doc/index.html
Cameyo User Guide (七牛镜像): http://cameyo.qiniudn.com/doc/index.html
本站 Cameyo相关文章:
Cameyo 官方资源库: http://online.cameyo.com/public
]]>Cameyo 是一款完全免费的应用程序虚拟化 (Application Virtualization) 工具或者说单文件软件制作工具,支持 XP、Vista 、 Windows7、Windows8,支持32位和64位系统。应用程序虚拟化技术就是将完整的程序资源打包为一个单一的可执行文件,从而无需安装即可运行。以前,要制作绿色软件需要学习很多技术,一般用户难以入门,而 Cameyo 则将此绿化过程变得简单且傻瓜。
Cameyo 的原理是利用沙盒(Sandbox)的虚拟化技术,先把所有相关资源打包成单个绿色文件,当执行这个“绿色软件”时,它会产生一个虚拟环境来执行,类似影子系统一样,一切涉及的操作都是在这个虚拟环境中完成,并不会去动原本的系统。所以使用 Cameyo 制作的绿色软件还有一个好处就是几乎不会对系统有害。
由于官方原版的翻译一直有问题,为了方便就自己修改编译一个,这个 PackageEditor 是基于官方源码,修改中文资源之后重新编译的,使用2.1版的源码主是要因为这个版本是个过渡版本,同时支持旧版和新的版本的编辑(只需要把不同版本的dll文件放进去就行了)。
]]>sudo
是linux下常用的允许普通用户使用超级用户权限的工具。 它的配置文件 sudoers 一般在 /etc 目录下。
不过不管 sudoers 文件在哪儿,sudo
都提供了一个编辑该文件的命令:visudo 来对该文件进行修改。强烈推荐使用该命令修改 sudoers,因为它会帮你校验文件配置是否正确,如果不正确,在保存退出时就会提示你哪段配置出错的。
以下是 sudoers 的默认配置文件内容。
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
<user list> <host list> = <operator list> <tag list> <command list>
username
,用户组加上%
,比如%admin
,再来看看默认配置里面的对应配置的说明
## root 用户可以在任意主机上以任意用户、组的权限执行任意命令,说明root用户具有最高级的权限。
root ALL=(ALL:ALL) ALL
## admin组的用户都拥有最高级权限。
%admin ALL=(ALL) ALL
## sudo 组用户和root用户权限一样
%sudo ALL=(ALL:ALL) ALL
tag list 如果是 NOPASSWD: 则运行时不需要输入密码例子:
## test 用户可以不用输入密码运行 **/sbin/reboot** 命令
test ALL=(ALL) NOPASSWD: /sbin/reboot
operator list 和 tag list 都是可选的,比如下面的:
test ALL=/sbin/reboot
实用例子, 在PHP
上使用system
调用系统命令时,由于是php
一般都是使用www
用户运行的,如果要特别的需要,需要处理某个用户的文件时就可以指定某个目录或命令,使用某个用户权限免密码运行。
例子: 目录 /mnt/sudodir 里面的程序可以使用root权限来执行。
www ALL=(root) NOPASSWD: /mnt/sudodir
使用时,直接sudo -u root /mnt/sudodir/cmd
,不需要输入密码。
为了安全起见,这个 /mnt/sudodir 除了root
用户之外其它人应该只有运行的权限。
查看当前用户的sudo
权限可以使用命令 sudo -l
PS: 我整理这些资料,主要是为了通过github的webhook功能, 配和我的VPS上的PHP脚本来实现 hexo
站点的自动更新,这样我只需要更新源文件到github上,它就自动生成站点内容,并且自动同步到多个不同的地方,有空我会再整一篇文章来介绍这个。
sudo
是linux下常用的允许普通用户使用超级用户权限的工具。 它的配置文件 sudoers 一般在 /etc 目录下。
不过不管 sudoers 文件在哪儿,sudo
都提供了一个编辑该文件的命令:visudo 来对该文件进行修改。强烈推荐使用该命令修改 sudoers,因为它会帮你校验文件配置是否正确,如果不正确,在保存退出时就会提示你哪段配置出错的。
以下是 sudoers 的默认配置文件内容。
]]>参数方面,这款与磊科的NR235W/NR236W以及热议的贝尔RG200E-CA非常接近,BCM5358 500MHz处理器,64MB RAM+16MB ROM的组合在其他品牌中算是高端配置了,接口包括1WAN+4LAN+1USB,算是齐全。
这款机器可以刷包括TOMATO、DD-WRT、磊科双WAN等多种固件,而且由于内置了JTAG接口,因此即使刷出问题也有挽救方案。很多玩家基于这款机器进行了各种DIY,包括升级RAM,增加天线等,价格不高,折腾余地很大。
这不我又开始折腾上了,由于默认情况下NVRAM只有32KB,平常的话使用起来倒是没有什么问题,不过若是你的配置的内容太多的超过32KB(像OpenVPN证书,一下就是10KB以上,很容易超),这时就会出现配置丢失的问题。
之前很早就发现了 ~╰独①儛② 提供的 HG320 64K CFE 刷了这个之后配合64K的固件就可以使用64K的NVRAM了,一直没有去尝试,最近又买了几个路由器,就拿来试试。
需要准备的软件ROM: 点这里下载
里面包括了 ~╰独①儛② 提供的CFE,还有 bwq518 提供的支持64K NVRAM的固件,还有TFTP、PUTTY等软件。
为了方便使用,先把连接路由器的网卡IP改成固定192.168.1.2,准备好TTL数据线,然后就是拆机了,按照下面方法接好TTL数据线,然后接上网线,电源。
首先要刷64K 的CFE,可以先刷DD的MINI版,然后在DD里面刷,或者在MINIWEB下刷,
相关资料:
http://www.right.com.cn/forum/thread-79340-1-1.html
我这里已经有TTL数据线了了,还是直接用TTL线刷比较快。
但不知什么原因我的TTL接上去之后什么都不显示,但经过测试输入命令有反应,最简单的就是输入reboot
之后路由器就会重启。所以本文介绍的是盲刷,只提供一个参考。
首先要启动到CFE模式,最保险的方法
打开TFTP程序
打开路由器,直到变绿.
这时ping 192.168.1.1
测试正常。并且TTL=100
说明这时已经停在了CFE界面。(如果一直没有办法进入,可以进入路由器管理界面,直接刷ddwrt固件重启之后一般就能行了)
可以开工了,直接运行tftpd32,不用管它,放着。
运行putty,选择对应的COM端口,和速度一般是(115200),然后连接。
可以试着输入’reboot’回车测试一下,如果路由器重启了,说明正常,重新使用上面的方法进入CFE界面。
首先清理NVRAM,在putty中直接输入以下命令回车(我这里是看不到回显的,只能盲打盲刷),下同。
nvram erase
然后开始刷64k的cfe。一切正常的话就会看到tftpd32的窗口会闪一下,并且会显示下载了cfe64k.bin文件。
flash -noheader 192.168.1.2:cfe64.bin flash0.boot
reboot
继续使用前面的方法进入CFE开始刷固件(也可以在上面输入reboot重启时,在putty窗口,按住Ctrl+C)。
quit
nvram erase
flash -ctheader 192.168.1.2:e1500.bin flash1.trx
注: 注意看一下TFTPD32的窗口,成功的话会有传e1500.bin文件的信息。 flash -noerase -noheader 192.168.1.2:64k.trx flash1.trx
注: 注意看一下TFTPD32的窗口,成功的话会有传64k.trx文件的信息。并且网络指示灯会一直在闪,表示正在上传固件。 reboot
一切正常的话,等待路由器重启完成之后就可以看到支持64K NVRAM的固件已经刷好了。
以后可以直接在路由器的固件升级功能中直接升级或刷其它固件。
参数方面,这款与磊科的NR235W/NR236W以及热议的贝尔RG200E-CA非常接近,BCM5358 500MHz处理器,64MB RAM+16MB ROM的组合在其他品牌中算是高端配置了,接口包括1WAN+4LAN+1USB,算是齐全。
这款机器可以刷包括TOMATO、DD-WRT、磊科双WAN等多种固件,而且由于内置了JTAG接口,因此即使刷出问题也有挽救方案。很多玩家基于这款机器进行了各种DIY,包括升级RAM,增加天线等,价格不高,折腾余地很大。
这不我又开始折腾上了,由于默认情况下NVRAM只有32KB,平常的话使用起来倒是没有什么问题,不过若是你的配置的内容太多的超过32KB(像OpenVPN证书,一下就是10KB以上,很容易超),这时就会出现配置丢失的问题。
]]>基于Hexo默认主题 light 修改而成,采用 bootstrap 框架
在尽量保留原有主题功能的同时采用模块化设计支持实现组件模块化.完全自定义,通过widgets你可以添加许多实用功能.可以自定义组合各种组件,像评论系统,统计系统等.
大部份的JS/CSS等静态文件都使用CDN加载,使用了 bootcss 和 qiniu 的CDN服务.
以下是本主题的特色:
基于Hexo默认主题light修改而成,采用bootstrap css框架,主要考虑多站点支持.
在尽量保留原有主题功能的同时采用模块化设计支持多个widgets.实现高度自定义,通过widgets你可以添加许多实用功能.
可以自定义组合各种组件,像评论系统,统计系统等.
$SOURCE\_$THEME.yml
[默认就是source\_chenall.yml]作为主题的配置文件,这样可以避免升级主题或其它原因导致的配置文件丢失).iLink
文章内链功能ijs
文章内嵌脚本或能source/_modules
目录).注: 上面的$SOURCE是hexo配置文件中在source_dir
,$THEME是hexo配置文件中的theme
,即 hexo.sourcedir + ‘‘+ hexo.config.theme+ ‘.yml’;
其它: 本主题可以轻松支持多站点,每个站点的配置各自独立,互不影响(包括站点特定插件等)。
效果见本站源码:https://github.com/chenall/chenall
还有demo源码: https://github.com/chenall/hexo-theme-chenall
site分支里面的文件就是文章源码,源码里面包括了对应的配置文件_config.yml和插件等。
安装hexo之后,再安装本主题。
然后下载本站源码,就可以使用新版的hexo测试了
例子:
svn co -r HEAD https://github.com/chenall/hexo-theme-chenall/trunk themes/chenall
svn co -r HEAD https://github.com/chenall/chenall/branches/site chenall.net
hexo server --config chenall.net/_config.yml
注2: V2.0版适用的hexo版本为 2.5.3 以上(2.5.2版本有Bug会显示不正常).2.4.X版请下载V1.0版主题.
通过以下命令下载主题到您的theme目录,然后修改blog的_config.yml
中theme为chenall
。
git clone git://github.com/chenall/hexo-theme-chenall.git themes/chenall
或
svn co -r HEAD https://github.com/chenall/hexo-theme-chenall/trunk themes/chenall
## 若要下载1.0版用以下命令
svn co https://github.com/chenall/hexo-theme-chenall/tags/V1.0 themes/chenall
另外: 主题内置的list_posts
插件还需要额外安装一个lodash
组件,使用以下命令安装即可.(V1.0版需要)
npm install lodash --save
通过以下命令来保持更新:
cd themes/light
git pull 或 svn up
hexo
默认的source
目录等虽然可以通过配置文件来指定,但由于必须使用固定的目录,使用起来不太灵活
本主题对此进行了扩展,允许这些目录跟随配置文件自动变化,比如下面的配置,最终的source_dir是$config/_config.yml
CustomDir:
source_dir: source
public_dir: public
说明:
本主题分类方式是额外实现的,一行一个分类,每一行都是一个独立分类.
同时支持多级分类,像下面的.就设置了两个分类,编程开发
和VBScript
,VBScript
是一个子分类.具体效果请参考demo
categories:
- 程序设计/VB/VBScript
- 编程开发
ijs
是本主题的内置的tag
插件,可以在文章中内嵌脚本,这样可以实现一些特殊功能.(因为是在主题中执行的,所以可以使用那些helper插件);
一个简单的例子,在文章中插入以下内容.
{% ijs %}
return link_to('http://chenall.net','我的搏客');
{% endijs %}
以上通过hexo内置的helper插件link_to实现在文章中插入一个链接指向http://chenall.net
.
复杂一些的例子,在文章中插入最新的5篇文章列表.
{% ijs %}
var str = '';
if (site.posts.length){
str = '<ul class="list-group">';
site.posts.sort('date', -1).limit(5).each(function(post){
str += '<li class="list-group-item"><a href="' + config.root + post.path + '">' + post.title + '</a></li>';
});
str += '</ul>';
}
return str;
{% endijs %}
iLink
是本主题内置的的tag
插件,通过iLink可以很方便的在文章中插入文章链接.
iLink 使用格式
{% iLink TYPE:VALUE%}
TYPE: 类型
VALUE: 值
其中TYPE可使用的值如下:
tag
链接到标签
{% iLink tag:GRUB4DOS %}
例:
cat
或 category
链接到分类
例子:
{% iLink cat:程序设计 %}
例:
其它值会根据提供的信息自动链接到指定文章
例子:
链接到源文件名
{% iLink source:_posts/grub4dos_dev.md %}
例:
链接到文章标题
{% iLink title:[推荐] 免费的云计算Koding %}
例:
若某个文章页有额外添加了一些信息比如id: 596
{% iLink id:597 %}
例:
通过文章的slug
{% iLink slug:jekyll_or_hexo %}
例:
如果你需要一些添加一些额外和主题无关的内容.这时就可以使用这个功能.
在_modules
目录中(主题或source都可以)新建一个文件夹partial
.
然后就可以通过partial
里面的特定文件添加额外内容.
具体文件列表:
body_start.ejs
标签<body>
后.body_end.ejs
标签</body>
前.head_start.ejs
标签<head>
后head_end.ejs
标签</head>
前例子: 想要在head中添加一行meta
信息就可以在head_start.ejs
中添加.
注: 配置中如果需要访问到本地路径,除非特别指定否则应该用css/theme.css
不要写成/css/theme.css
,前者是相对路径会自动添加config.root路径.后者是绝对路径.
本主题特色: 把这个配置文件复制到source
目录下并改名为_chenall.yml
则会优先使用该配置,这样可以避免由于升级主题或其它原因导致的配置丢失.更方便使用.
# Site default meta keywords
#keywords: site, wide, default, keywords
#已加载的模块,按顺序加载,所以需要自己调整加载的顺序,比如jquery一般要加载在最前面
loaded_modules:
- jquery
- bootstrap
- fontawesome
- prettify
- fancybox
- mathjax
# 注: 模块是由css或js文件来实现的,部份需要附加js代码的模块在_modules目录下.
# 如: prettify 如果加载了prettify则会同时加载_modules\_modules.ejs
# 部份模块是自动按需加载的,在模板中添加如下代码加载多说的JS模块
# <% theme.add_module('duoshuo'); %>
#
#
modules:
# respond 不要放到loaded_modules中,这个会自动加载
# proxy 指定respond的proxy地址
# 注: bootstrap的css文件和这个proxy需要在同一个域上
respond: ## A fast & lightweight polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more).
js: http://cdn.staticfile.org/respond.js/1.4.2/respond.min.js
proxy: http://cdn.staticfile.org/respond.js/1.4.2/respond-proxy.html
jquery:
js: http://cdn.bootcss.com/jquery/1.10.2/jquery.min.js
bootstrap: #强大的CSS框架,由Twitter的开发工程师推出
css: http://cdn.staticfile.org/twitter-bootstrap/3.1.0/css/bootstrap.min.css
js: http://cdn.staticfile.org/twitter-bootstrap/3.1.0/js/bootstrap.min.js
prettify: # Google Code Prettify 代码的高亮显示
css: http://cdn.bootcss.com/prettify/r298/prettify.min.css
js: http://cdn.bootcss.com/prettify/r298/prettify.min.js
highlightjs: # highlight.js 代码高亮显示插件
css: http://cdn.bootcss.com/highlight.js/7.4/styles/github.min.css
js: http://cdn.bootcss.com/highlight.js/7.4/highlight.min.js
fancybox: # 一款基于jQuery开发的类Lightbox插件
css: http://cdn.bootcss.com/fancybox/2.1.5/jquery.fancybox.min.css
js: http://cdn.bootcss.com/fancybox/2.1.5/jquery.fancybox.min.js
imagesloaded: #监测图片是否加载完毕的JavaScript库
#js: js/jquery.imagesloaded.min.js
js: http://cdn.bootcss.com/jquery.imagesloaded/3.0.4/jquery.imagesloaded.min.js
Gallery:
css: http://cdn.bootcss.com/blueimp-gallery/2.11.2/css/blueimp-gallery.min.css
js: http://cdn.bootcss.com/blueimp-gallery/2.11.2/js/jquery.blueimp-gallery.min.js
fontawesome:
css: http://cdn.bootcss.com/font-awesome/4.0.3/css/font-awesome.min.css
# MathJax is an open source JavaScript display engine for mathematics that works in all browsers.
mathjax: # 生成数学公式插件
css:
js: http://cdn.bootcss.com/mathjax/2.3/MathJax.js?config=TeX-AMS-MML_HTMLorMML
#js: http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML
uyan: #有言评论系统
uid: 1880458
ujian: #友荐:为网站添加'猜你喜欢'功能
uid: 1880458
##评论功能设置,目前支持disqus和duoshuo/uyan,需要在上面的modules中进行要应的设置
# show_count 是否显示文章的评论数量
# short_name 对应的short_name
# 需要的其它参数也可以加在下面,然后自己修改模板来使用.theme.comments.xxxxxx来调用
#
#
comments:
provider: duoshuo
show_count: true
short_name: hexochenall
## 站点分析统计代码功能组件
# 加载在站点的footer位置
analytics:
# provider 要加载的统计代码类型,可同时加载多少,使用","分隔. 如下就加载了51la和google的统计代码
# provider: 51la,google
provider: 51la,google,cnzz
# google-analytics UA
google:
# 我要啦」免费统计 ID
51la:
# cnzz 免费统计
cnzz:
siteid: 5774006 #站点ID,在获取统计代码的页面的地址栏上可以看到siteid=xxxx或从代码中提取(一般是一串数字)
show: #显示样式 留空: 图片形式1; 1: 图片形式2; 2: 图片形式1; 其它值: 文字形式
# 站点顶部菜单,支持子菜单
menu:
Home: ''
About: about/
Archives: archives/
其它链接:
chenall: //chenall.net
gihtub: https://github.com/chenall/hexo-theme-chenall
# ajax_widgets是否使用jquery.load动态加载widget的内容,
# 注: 部份小工具,像标签,分类,最近文章等,这些工具的内容在所有页面都是一样的,这时它就支持动态加载
# 所谓的动态加载,就是把这些内容从文章中分离出来独立存在,并采用ajax技术动态加载到指定位置.
# 使用动态加载,更新文章时,就不会因为分类或标签等内容的更改,导致所有页面都需要更新.
#
ajax_widgets: true
# 要加载的工具在这里添加
widgets:
header: #顶部
footer: #底部
sidebar: #侧边栏
- search
- category
- recent_posts
- tagcloud
- latest_update_posts
- random_posts
- sina_weiboshow
- recent_comments
before_content: # 文章内容前
after_content: # 文章内容后
- wumiiRelatedItems
- post_footer_info
- ujian
after_post: # 文章框架之后
- post_pageNav
- related_posts
# For use with tagcloud or tag widgets
# - only tags >= to tag_minium are shown
tag_minium: 3
## Google 跟踪代码管理器 设置
## https://www.google.com/tagmanager/
## ID 就是对应容器的ID
## GoogleTagManagerID: GTM-ABCDEF
GTM_ID:
## 在文章中使用'[ CDN_URL]:'(注:CDN_URL两边无任格空格,这里是为了防止被替换)字符串自动替换为下面的地址,主要是为了方便使用.
CDN_URL: http://your.cdn.url
twitter_id: chenall
facebook_id:
linkedin_id:
github_id: chenall/almrun
rss: atom.xml
本主题只设置了简体中文语言文件,要使用其它语言,可以自己翻译下.以下是简体中文的语言文件例子:
categories: 分类
search: 搜索
tags: 标签
tagcloud: 标签云
tweets: 推文
prev: 上一页
next: 下一页
comment: 留言
archive_a: 归档
archive_b: 归档:%s
page: 第 %d 页
post:
updated: 最近更新
Tagged: 标签
Posted on: 发表于
Posted in: 归类
read more: 阅读全文
menu:
Home: 主页
About: 关于
Archives: 归档
GuestBook: 留言板
widgets:
category: 分类
recent_posts: 最近文章
latest_update_posts: 最近更新
recent_comments: 最近评论
sina_weiboshow: 新浪微搏秀
google_sidebar: 赞助商
tags: 标签
tagcloud: 标签云
]]>基于Hexo默认主题 light 修改而成,采用 bootstrap 框架
在尽量保留原有主题功能的同时采用模块化设计支持实现组件模块化.完全自定义,通过widgets你可以添加许多实用功能.可以自定义组合各种组件,像评论系统,统计系统等.
大部份的JS/CSS等静态文件都使用CDN加载,使用了 bootcss 和 qiniu 的CDN服务.
以下是本主题的特色:
基于Hexo默认主题light修改而成,采用bootstrap css框架,主要考虑多站点支持.
在尽量保留原有主题功能的同时采用模块化设计支持多个widgets.实现高度自定义,通过widgets你可以添加许多实用功能.
可以自定义组合各种组件,像评论系统,统计系统等.
$SOURCE\_$THEME.yml
[默认就是source\_chenall.yml]作为主题的配置文件,这样可以避免升级主题或其它原因导致的配置文件丢失).iLink
文章内链功能ijs
文章内嵌脚本或能source/_modules
目录).前段时间在尝试静态博客,之后决定使用hexo,然后就是一系列的折腾再折腾.设计完善本主题,对hexo进行改进(大部份改进已经并入到官方主源码分支).
在这期间,学习到了很多新的知识.
本主题是自己设计的高度模块化hexo主题.加入了很多独特的功能,也是我学习过程中的经验累积.
目前暂时没有发现什么太大的问题.以后还会慢慢完善
有兴趣你也可以试试,^_^,有什么疑问可以在本站留言
<script src="https://google-code-prettify.googlecode.com/svn/loader/prettify.js"></script>
<script src="https://google-code-prettify.googlecode.com/svn/loader/prettify.css"></script>
然后在文章尾部添加代码实现自动高亮显示
<script type="text/javascript">
$(window).load(function(){
$("pre").addClass("prettyprint");
prettyPrint();
})
<script type="text/javascript">
或使用run_prettify来自动加载
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?lang=css&skin=sunburst"></script>
但是上面都是有缺点的:
所以这里就给一个变通的方法,实现了根据需要自动加载对应语言的通用JS代码.不受路径限制,自动获取prettify文件的路径,自动加载需要的代码高亮文件.
需要jquery的支持.
<script type="text/javascript">
var lang=[];
var pretty_base='';
$('script').each(function(){
var c = $(this).attr('src');
if (!c)
return;
if (c.match(/(\/)?prettify(\.min)?\.js/i))
{
var index = c.lastIndexOf('/');
if (index != -1)
pretty_base = c.substr(0,index + 1);
return false;
}
})
$('pre code').each(function(){
var c = $(this).attr('class')
if (!c)
return;
c = c.match(/\s?(lang\-\w+)/i);
if (c && lang.indexOf(c[1]) == -1)
{
lang.push(c[1]);
$.getScript(pretty_base + c[1] + '.min.js');
}
})
$(window).load(function(){
$("pre").addClass("prettyprint");
prettyPrint();
})
</script>
]]>首先就是加载css和js文件
]]>
支持一键安装各种程序,像WORDPRESS之类的,很简单.
支持在线编写代码,编译等..支持主流环境PHP,PYTHON,PERL,RUBY
以上是建站的功能,上说说过了它是一个linux虚拟机,可以进入linux命令行,使用一些linux的功能.
你完全可以用这个熟悉下linux的操作,还有更多功能等着你自己去发现.
全英文的,自己翻译下,不懂可以上Google搜一下.
其它的不多说了(因为国情原因,不能说太多),懂行的赶紧注册收藏一个吧.
附上注册地址:Koding注册地址
]]>LuaJIT is a Just-In-Time Compiler (JIT) for the Lua programming language. Lua is a powerful, dynamic and light-weight programming language. It may be embedded or used as a general-purpose, stand-alone language.
LuaJIT is Copyright © 2005-2013 Mike Pall, released under the MIT open source license.
LuaJIT对原版LUA进行了一些扩展,功能更强大,实用,速度也更快.本文主要介绍一下FFI扩展功能.
FFI库允许调用外部C函数以及使用C数据结构.这意味着我们可以通过它来调用一些系统API或DLL的函数,像调用LIBCURL来实现网络功能.等…
比如以下来自官网最简单的应用代码
--Load the FFI library.
local ffi = require("ffi")
--Add a C declaration for the function. The part inside the double-brackets (in green) is just standard C syntax.
ffi.cdef[[
int printf(const char *fmt, ...);
]]
--Call the named C function — Yes, it's that simple!
ffi.C.printf("Hello %s!", "world")
local ffi = require("ffi")
ffi.cdef[[
int MessageBoxA(void *w, const char *txt, const char *cap, int type);
]]
ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0)
看起来很简单不是吗?
这里给一个稍微复杂一些的例子,这是我在是学习过程中碰到的一些问题的总结,里面包括了一些常用的操作,像ffi.new 创建一个C的类型,ffi.cast数据类型转换,等.有兴趣的可以通过这个例子来学习一下如何应用.少走一些弯路.希望对大家有用.
本代码要保存为ANSI格式才可以正常运行
local ffi = require("ffi")
ffi.cdef[[
typedef char TCHAR;
typedef unsigned int UINT;
typedef TCHAR _LPTSTR;
typedef const TCHAR *LPCTSTR;
typedef LPCTSTR LPCSTR;
typedef UINT WPARAM;
typedef unsigned long LPARAM;
typedef UINT HWND;
typedef struct {
long x;
long y;
} POINT,_PPOINT;
void* malloc(size_t size);
void* free(void* memblock);
bool GetCursorPos(PPOINT lpPoint);
HWND WindowFromPoint(POINT Point);
int GetWindowTextA(HWND hWnd, LPTSTR lpString, int nMaxCount);
bool SetWindowTextA(HWND hWnd, LPCTSTR lpString);
int SendMessageA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int MessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType);
]]
local user32 = ffi.load("User32.dll")--WINDOWS API函数所在DLL文件
local win32 = ffi.load('msvcrt.dll')--malloc和free函数
local pos=ffi.new("POINT");
local oks = user32.GetCursorPos(pos)--获取当前鼠标位置
local IDYES = 6
local IDNO = 7
local WM_SETTEXT = 0x000C
local WM_GETTEXT = 0x000D
if oks then
local hwnd = user32.WindowFromPoint(pos)--获取指定位置下窗体的句柄
local lpString = ffi.new("char*",win32.malloc(1024))--分配内存
local test = user32.GetWindowTextA(hwnd,lpString,1023)--获取文本
local str1 = ffi.string(lpString);
local strtest ="FFI 调用SetWindowText功能测试"
local t = user32.MessageBoxA(0,"是否把以下窗体\n<"..str1..">\n的标题修改为以下内容:\n"..strtest,"LUAJIT FFI 调用WINAPI测试",0x44)--MB_ICONINFORMATION || 0x00000004L
if t == IDYES then
if user32.SetWindowTextA(hwnd,strtest) == true then
user32.MessageBoxA(0,"修改成功","测试",0x40)
end
end
--[[注: Windows API 的SendMessage就是SendMessageA或SendMessageW
像MessageBox也是类型的MessageBoxA和MessageBoxW
本文例子使用了ffi.cast进行了数据类型的转换,如果不想转换可以修改一下SendMessageA的定义改为如下(我最早就是不知道有ffi.cast所以用的修改定义的方法)
int SendMessageA(HWND hwnd, UINT msg, WPARAM wParam, LPCTSTR lParam);
就可以直接使用了,例:
user32.SendMessageA(hwnd,WM_SETTEXT,1024,"用SendMessage和WM_SETTEXT功能改写目标字符串")
这个SendMessage是WINDOWS一个很重要的API,后面的两个参数很灵活,根据不同的功能需求,可以是这符串/数字或指针,数组之类的.--]]
user32.MessageBoxA(0,"测试使用SendMessage来实现同样的功能","测试2",0x40)
user32.SendMessageA(hwnd,WM_GETTEXT,1024,ffi.cast("LPARAM",lpString))--通过ffi.cast功能进行类型转换
user32.MessageBoxA(0,"用SendMessage和WM_GETTEXT功能获取到的窗体标题为\n"..ffi.string(lpString),"测试2",0x40);
user32.SendMessageA(hwnd,WM_SETTEXT,1024,ffi.cast("LPARAM","用SendMessage和WM_SETTEXT功能改写目标字符串"))
user32.MessageBoxA(0,"目标标题已改变","测式2",0x40)
win32.free(lpString)--释放内存
end
]]>LuaJIT is a Just-In-Time Compiler (JIT) for the Lua programming language. Lua is a powerful, dynamic and light-weight programming language. It may be embedded or used as a general-purpose, stand-alone language.
LuaJIT is Copyright © 2005-2013 Mike Pall, released under the MIT open source license.
LuaJIT对原版LUA进行了一些扩展,功能更强大,实用,速度也更快.本文主要介绍一下FFI扩展功能.
]]>
这几天系统地学习了一下Lua这个脚本语言,Lua脚本是一个很轻量级的脚本,也是号称性能最高的脚本,用在很多需要性能的地方,比如:游戏脚本,nginx,wireshark的脚本,当你把他的源码下下来编译后,你会发现解释器居然不到200k,这是多么地变态啊(/bin/sh都要1M,MacOS平台),而且能和C语言非常好的互动。我很好奇得浏览了一下Lua解释器的源码,这可能是我看过最干净的C的源码了。
我不想写一篇大而全的语言手册,一方面是因为已经有了(见本文后面的链接),重要的原因是,因为大篇幅的文章会挫败人的学习热情,我始终觉得好的文章读起来就像拉大便一样,能一口气很流畅地搞完,才会让人爽(这也是我为什么不想写书的原因)。所以,这必然又是一篇”入厕文章”,还是那句话,我希望本文能够让大家利用上下班,上厕所大便的时间学习一个技术。呵呵。
相信你现在已经在厕所里脱掉裤子露出屁股已经准备好大便了,那就让我们畅快地排泄吧……
首先,我们需要知道,Lua是类C的,所以,他是大小写字符敏感的。
下面是Lua的Hello World。注意:Lua脚本的语句的分号是可选的,这个和GO语言很类似。
print("Hello World")
你可以像python一样,在命令行上运行lua命令后进入lua的shell中执行语句。
chenhao-air:lua chenhao$ lua
Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio
> print("Hello, World")
Hello, World
>
也可以把脚本存成一个文件,用如下命令行来运行。
>lua file.lua
或是像shell一样运行:
chenhao-air:lua chenhao$ cat hello.lua
#!/usr/local/bin/lua
print("Hello, World")
chenhao-air:lua chenhao$ chmod +x hello.lua
chenhao-air:test chenhao$ ./hello.lua
Hello, World
-- 两个减号是行注释
--[[
这是块注释
这是块注释
--]]
Lua的数字只有double型,64bits,你不必担心Lua处理浮点数会慢(除非大于100,000,000,000,000),或是会有精度问题。
你可以以如下的方式表示数字,0x开头的16进制和C是很像的。
num = 1024
num = 3.0
num = 3.1416
num = 314.16e-2
num = 0.31416E1
num = 0xff
num = 0x56
字符串你可以用单引号,也可以用双引号,还支持C类型的转义,比如: ‘\a’ (响铃), ‘\b’ (退格), ‘\f’ (表单), ‘\n’ (换行), ‘\r’ (回车), ‘\t’ (横向制表), ‘\v’ (纵向制表), ‘\\‘ (反斜杠), ‘\“‘ (双引号), 以及 ‘\“ (单引号)
下面的四种方式定义了完全相同的字符串(其中的两个中括号可以用于定义有换行的字符串)
a = 'alo\n123"'
a = "alo\n123\""
a = '\97lo\10\04923"'
a = [[alo
123"]]
C语言中的NULL在Lua中是nil,比如你访问一个没有声明过的变量,就是nil,比如下面的v的值就是nil
v = UndefinedVariable
布尔类型只有nil和false是 false,数字0啊,’’空字符串(’\0’)都是true!
另外,需要注意的是:lua中的变量如果没有特殊说明,全是全局变量,那怕是语句块或是函数里。变量前加local关键字的是局部变量。
theGlobalVar = 50
local theLocalVar = "local variable"
不多说了,直接看代码吧(注意:Lua没有++或是+=这样的操作)
sum = 0
num = 1
while num <= 100 do
sum = sum + num
num = num + 1
end
print("sum =",sum)
if age == 40 and sex =="Male" then
print("男人四十一枝花")
elseif age > 60 and sex ~="Female" then
print("old man without country!")
elseif age < 20 then
io.write("too young, too naive!\n")
else
local age = io.read()
print("Your age is "..age)
end
上面的语句不但展示了if-else语句,也展示了
1)“~=”是不等于,而不是!=
2)io库的分别从stdin和stdout读写的read和write函数
3)字符串的拼接操作符“..”
另外,条件表达式中的与或非为分是:and, or, not关键字。
从1加到100
sum = 0
for i = 1, 100 do
sum = sum + i
end
从1到100的奇数和
sum = 0
for i = 1, 100, 2 do
sum = sum + i
end
从100到1的偶数和
sum = 0
for i = 100, 1, -2 do
sum = sum + i
end
sum = 2
repeat
sum = sum ^ 2 --幂操作
print(sum)
until sum >1000
Lua的函数和Javascript的很像
function fib(n)
if n < 2 then return 1 end
return fib(n - 2) + fib(n - 1)
end
同样,Javascript附体!
function newCounter()
local i = 0
return function() -- anonymous function
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) --> 1
print(c1()) --> 2
示例二
function myPower(x)
return function(y) return y^x end
end
power2 = myPower(2)
power3 = myPower(3)
print(power2(4)) --4的2次方
print(power3(5)) --5的3次方
和Go语言一样,可以一条语句上赋多个值,如:
name, age, bGay = "haoel", 37, false, "haoel@hotmail.com"
上面的代码中,因为只有3个变量,所以第四个值被丢弃。
函数也可以返回多个值:
function getUserInfo(id)
print(id)
return "haoel", 37, "haoel@hotmail.com", "http://coolshell.cn"
end
name, age, email, website, bGay = getUserInfo()
注意:上面的示例中,因为没有传id,所以函数中的id输出为nil,因为没有返回bGay,所以bGay也是nil。
函数前面加上local就是局部函数,其实,Lua中的函数和Javascript中的一个德行。
比如:下面的两个函数是一样的:
function foo(x) return x^2 end
foo = function(x) return x^2 end
所谓Table其实就是一个Key Value的数据结构,它很像Javascript中的Object,或是PHP中的数组,在别的语言里叫Dict或Map,Table长成这个样子:
haoel = {name="ChenHao", age=37, handsome=True}
下面是table的CRUD操作:
haoel.website="http://coolshell.cn/"
local age = haoel.age
haoel.handsome = false
haoel.name=nil
上面看上去像C/C++中的结构体,但是name,age, handsome, website都是key。你还可以像下面这样写义Table:
t = {[20]=100, ['name']="ChenHao", [3.14]="PI"}
这样就更像Key Value了。于是你可以这样访问:t[20],t[“name”], t[3.14]。
我们再来看看数组:
arr = {10,20,30,40,50}
这样看上去就像数组了。但其实其等价于:
arr = {[1]=10, [2]=20, [3]=30, [4]=40, [5]=50}
所以,你也可以定义成不同的类型的数组,比如:
arr = {"string", 100, "haoel", function() print("coolshell.cn") end}
注:其中的函数可以这样调用:arr4。
我们可以看到Lua的下标不是从0开始的,是从1开始的。
for i=1, #arr do
print(arr[i])
end
注:上面的程序中:#arr的意思就是arr的长度。
注:前面说过,Lua中的变量,如果没有local关键字,全都是全局变量,Lua也是用Table来管理全局变量的,Lua把这些全局变量放在了一个叫”_G”的Table里。
我们可以用如下的方式来访问一个全局变量(假设我们这个全局变量名叫globalVar):
_G.globalVar
_G["globalVar"]
我们可以通过下面的方式来遍历一个Table。
for k, v in pairs(t) do
print(k, v)
end
MetaTable和MetaMethod是Lua中的重要的语法,MetaTable主要是用来做一些类似于C++重载操作符式的功能。
比如,我们有两个分数:
fraction_a = {numerator=2, denominator=3}
fraction_b = {numerator=4, denominator=7}
我们想实现分数间的相加:2/3 + 4/7,我们如果要执行: fraction_a + fraction_b,会报错的。
所以,我们可以动用MetaTable,如下所示:
fraction_op={}
function fraction_op.__add(f1, f2)
ret = {}
ret.numerator = f1.numerator * f2.denominator + f2.numerator * f1.denominator
ret.denominator = f1.denominator * f2.denominator
return ret
end
为之前定义的两个table设置MetaTable:(其中的setmetatble是库函数)
setmetatable(fraction_a, fraction_op)
setmetatable(fraction_b, fraction_op)
于是你就可以这样干了:(调用的是fraction_op.__add()函数)
fraction_s = fraction_a + fraction_b
至于__add这是MetaMethod,这是Lua内建约定的,其它的还有如下的MetaMethod:
__add(a, b) 对应表达式 a + b
__sub(a, b) 对应表达式 a - b
__mul(a, b) 对应表达式 a * b
__div(a, b) 对应表达式 a / b
__mod(a, b) 对应表达式 a % b
__pow(a, b) 对应表达式 a ^ b
__unm(a) 对应表达式 -a
__concat(a, b) 对应表达式 a .. b
__len(a) 对应表达式 #a
__eq(a, b) 对应表达式 a == b
__lt(a, b) 对应表达式 a < b
__le(a, b) 对应表达式 a <= b
__index(a, b) 对应表达式 a.b
__newindex(a, b, c) 对应表达式 a.b = c
__call(a, ...) 对应表达式 a(...)
上面我们看到有__index这个重载,这个东西主要是重载了find key的操作。这操作可以让Lua变得有点面向对象的感觉,让其有点像Javascript的prototype。(关于Javascrip的面向对象,你可以参看我之前写的Javascript的面向对象)
所谓__index,说得明确一点,如果我们有两个对象a和b,我们想让b作为a的prototype只需要:
setmetatable(a, {__index = b})
例如下面的示例:你可以用一个Window_Prototype的模板加上__index的MetaMethod来创建另一个实例:
Window_Prototype = {x=0, y=0, width=100, height=100}
MyWin = {title="Hello"}
setmetatable(MyWin, {__index = Window_Prototype})
于是:MyWin中就可以访问x, y, width, height的东东了。(注:当表要索引一个值时如table[key], Lua会首先在table本身中查找key的值, 如果没有并且这个table存在一个带有index属性的Metatable, 则Lua会按照index所定义的函数逻辑查找)
有了以上的基础,我们可以来说说所谓的Lua的面向对象。
Person={}
function Person:new(p)
local obj = p
if (obj == nil) then
obj = {name="ChenHao", age=37, handsome=true}
end
self.__index = self
return setmetatable(obj, self)
end
function Person:toString()
return self.name .." : ".. self.age .." : ".. (self.handsome and "handsome" or "ugly")
end
上面我们可以看到有一个new方法和一个toString的方法。其中:
1)self 就是 Person,Person:new(p),相当于Person.new(self, p)
2)new方法的self.__index = self 的意图是怕self被扩展后改写,所以,让其保持原样
3)setmetatable这个函数返回的是第一个参数的值。
于是:我们可以这样调用:
me = Person:new()
print(me:toString())
kf = Person:new{name="King's fucking", age=70, handsome=false}
print(kf:toString())
继承如下,我就不多说了,Lua和Javascript很相似,都是在Prototype的实例上改过来改过去的。
Student = Person:new()
function Student:new()
newObj = {year = 2013}
self.__index = self
return setmetatable(newObj, self)
end
function Student:toString()
return "Student : ".. self.year.." : " .. self.name
end
我们可以直接使用require(“model_name”)来载入别的lua文件,文件的后缀是.lua。载入的时候就直接执行那个文件了。比如:
我们有一个hello.lua的文件:
print("Hello, World!")
如果我们:require(“hello”),那么就直接输出Hello, World!了。
注意:
1)require函数,载入同样的lua文件时,只有第一次的时候会去执行,后面的相同的都不执行了。
2)如果你要让每一次文件都会执行的话,你可以使用dofile(“hello”)函数
3)如果你要玩载入后不执行,等你需要的时候执行时,你可以使用 loadfile()函数,如下所示:
local hello = loadfile("hello")
... ...
... ...
hello()
loadfile(“hello”)后,文件并不执行,我们把文件赋给一个变量hello,当hello()时,才真的执行。(我们多希望JavaScript也有这样的功能(参看《Javascript 装载和执行》))
当然,更为标准的玩法如下所示。
假设我们有一个文件叫mymod.lua,内容如下:
local HaosModel = {}
local function getname()
return "Hao Chen"
end
function HaosModel.Greeting()
print("Hello, My name is "..getname())
end
return HaosModel
于是我们可以这样使用:
local hao_model = require("mymod")
hao_model.Greeting()
其实,require干的事就如下:(所以你知道为什么我们的模块文件要写成那样了)
local hao_model = (function ()
--mymod.lua文件的内容--
end)()
我估计你差不多到擦屁股的时间了,所以,如果你还比较喜欢Lua的话,下面是几个在线文章你可以继续学习之:
关于Lua的标库,你可以看看官方文档:string, table, math, io, os。
本文章作者和出处: 酷壳 – CoolShell.cn ,请勿用于任何商业用途
]]>这几天系统地学习了一下Lua这个脚本语言,Lua脚本是一个很轻量级的脚本,也是号称性能最高的脚本,用在很多需要性能的地方,比如:游戏脚本,nginx,wireshark的脚本,当你把他的源码下下来编译后,你会发现解释器居然不到200k,这是多么地变态啊(/bin/sh都要1M,MacOS平台),而且能和C语言非常好的互动。我很好奇得浏览了一下Lua解释器的源码,这可能是我看过最干净的C的源码了。
我不想写一篇大而全的语言手册,一方面是因为已经有了(见本文后面的链接),重要的原因是,因为大篇幅的文章会挫败人的学习热情,我始终觉得好的文章读起来就像拉大便一样,能一口气很流畅地搞完,才会让人爽(这也是我为什么不想写书的原因)。所以,这必然又是一篇”入厕文章”,还是那句话,我希望本文能够让大家利用上下班,上厕所大便的时间学习一个技术。呵呵。
相信你现在已经在厕所里脱掉裤子露出屁股已经准备好大便了,那就让我们畅快地排泄吧……
]]>我看了一下觉得真的很不错,真是太适合像我这样的懒人了,直接使用MarkDown语法写博客,使用一些简单的标记就可以实现一些排版等。
比如 Yonsm 这个就是使用jekyll的,我也打算使用jekyll来写搏客,不过由于对这个还不太熟悉所以就先了解下情况,后来又发现了Hexo,它使用node.js 速度更快,不知用哪个好,所以就两个都试了。
首先就是测试平台的搭建,想要在Windows上搭建还是有些麻烦的,虽然网上有很多教程,但是你一步一步下来还是会发现许多问题,我就碰到了好几个问题(主要还是程序版本问题嘿)。
像Python要用2.x的,pygments插件要用0.5.0的。
还有中文编码问题
... invalid byte sequence in GBK ..
在网上找了一下,大多是说要修改jekyll程序的文件,本来我也想改,不过看了一下发现原来新版的已经不需要这样修改了
直接在配置文件_config.yam中添加一行’encoding: UTF-8’就行了。
经过各种折腾总算把测试平台建好了,我比较喜欢绿色化,所以顺便绿色化了一下,有需要的可以留言,我再上传(7z压缩后100MB左右,解压后400MB左右python27+ruyb193+nodejs+svn+git+XXX需要的基本都有了)
再来说下经过我试用后的比较,个人比较喜欢Hexo,因为它的功能还有扩展性都比较强,速度也快。
jekyll 更新比较快,调试信息比较清楚,而且Github原生支持,只是产生的速度慢一些。
另外jekyll 受限于Liquid语法对于修改模板来说真的很不方便,如果可以用其它语法就好了,当然如果你不需要修改模板就没有什么问题了。
分别用jekyll和Hexo生成了两个网站,有兴趣可以去观赏下。
jekyll 托管在github上(作为ALMRUN程序的主页) http://almrun.chenall.net
hexo 托管在BAE上 http://hexo.chenall.net
2014-01-10 经过测试比较后,最后我决定采用Hexo
]]>目前该主机商给LEB读者发布了一个优惠码,只要在付款时在Promotional Code
用中输入”LEB”优惠码价格就会变成原价的%50.01.
我入手的这一款配置信息,很实惠有木有啊..月付$1.99,年付$9.99,当然是选择年付了.
CPU:2 cores
内存:512MB
vSWAP:512MB
硬盘:5 GB
月流量:500GB
1 IP/KiwiVM
VPS 5G订购链接 晚了可能就没有了,
由于是在国外的在国内的访问速度肯定没有那么如意,偶尔还会抽风,拿来练手倒是不错,才几十块钱,..
有需要的话可以自己去选购,需要使用PayPal或支持美元的信用卡支付,也可以联系我代购.
其它配置信息,当然了也可以选择季度付款,或半年付款.年付价格都会比较便宜,
VPS3G 1CPU/256MB/3G/50G流量 $2.99/月
VPS10G 1CPU/512MB/10G/200G $4.99/月或$39.99/年 折后只需要$19.99/年
VPS50G 1CPU/1024MB/50G/500G $9.99/月
]]>比如”中华人民共和国” 是ZHRMGHG
最近在ALMRun程序就用到了这个方法,,顺便写了一下PHP版的.感觉PHP的更简单哈,
适用于要求不是很高的场合,因为这个没有处理多音字,只支持GB2312字符,不过优点就是足够简单,几行代码的问题.有需要的可以拿去用,欢迎报错.
源码: https://github.com/chenall/chenall/blob/master/php/tools/ZH-cn_TO_pinyin.php
<?php
/*
中文汉字转拼音首字母的PHP简易实现方法.
要求: 只能是GB2312码表里面中文字符
转换得到字符串对应的拼音首字母大写.
来源: http://chenall.net/
用法:
echo zh2py::conv('Chinese 中华人民共和国');//Chinese ZHRMGHG
或
$py = new zh2py;
echo $py->conv('Chinese 中华人民共和国');//Chinese ZHRMGHG
*/
class zh2py
{
//根据汉字区位表,(http://www.mytju.com/classcode/tools/QuWeiMa_FullList.asp)
//我们可以看到从16-55区之间是按拼音字母排序的,所以我们只需要判断某个汉字的区位码就可以得知它的拼音首字母.
//区位表第一部份,按拼音字母排序的.
//16区-55区
/*
'A'=>0xB0A1, 'B'=>0xB0C5, 'C'=>0xB2C1, 'D'=>0xB4EE, 'E'=>0xB6EA, 'F'=>0xB7A2, 'G'=>0xB8C1,'H'=>0xB9FE,
'J'=>0xBBF7, 'K'=>0xBFA6, 'L'=>0xC0AC, 'M'=>0xC2E8, 'N'=>0xC4C3, 'O'=>0xC5B6, 'P'=>0xC5BE,'Q'=>0xC6DA,
'R'=>0xC8BB, 'S'=>0xC8F6, 'T'=>0xCBFA, 'W'=>0xCDDA, 'X'=>0xCEF4, 'Y'=>0xD1B9, 'Z'=>0xD4D1
*/
private static $FirstTable = array(
0xB0C5, 0xB2C1, 0xB4EE, 0xB6EA, 0xB7A2, 0xB8C1, 0xB9FE, 0xBBF7, 0xBFA6, 0xC0AC, 0xC2E8,
0xC4C3, 0xC5B6, 0xC5BE, 0xC6DA, 0xC8BB, 0xC8F6, 0xCBFA, 0xCDDA, 0xCEF4, 0xD1B9, 0xD4D1,0xD7FA
);
private static $FirstLetter = "ABCDEFGHJKLMNOPQRSTWXYZ";
//区位表第二部份,不规则的,下面的字母是每个区里面对应字的拼音首字母.从网上查询整理出来的,可能会有部份错误.
//56区-87区
private static $SecondTable = array(
"CJWGNSPGCGNEGYPBTYYZDXYKYGTZJNMJQMBSGZSCYJSYYFPGKBZGYDYWJKGKLJSWKPJQHYJWRDZLSYMRYPYWWCCKZNKYYG",
"TTNGJEYKKZYTCJNMCYLQLYPYSFQRPZSLWBTGKJFYXJWZLTBNCXJJJJTXDTTSQZYCDXXHGCKBPHFFSSTYBGMXLPBYLLBHLX",
"SMZMYJHSOJNGHDZQYKLGJHSGQZHXQGKXZZWYSCSCJXYEYXADZPMDSSMZJZQJYZCJJFWQJBDZBXGZNZCPWHWXHQKMWFBPBY",
"DTJZZKXHYLYGXFPTYJYYZPSZLFCHMQSHGMXXSXJYQDCSBBQBEFSJYHWWGZKPYLQBGLDLCDTNMAYDDKSSNGYCSGXLYZAYPN",
"PTSDKDYLHGYMYLCXPYCJNDQJWXQXFYYFJLEJPZRXCCQWQQSBZKYMGPLBMJRQCFLNYMYQMSQYRBCJTHZTQFRXQHXMQJCJLY",
"QGJMSHZKBSWYEMYLTXFSYDXWLYCJQXSJNQBSCTYHBFTDCYZDJWYGHQFRXWCKQKXEBPTLPXJZSRMEBWHJLBJSLYYSMDXLCL",
"QKXLHXJRZJMFQHXHWYWSBHTRXXGLHQHFNMGYKLDYXZPYLGGSMTCFBAJJZYLJTYANJGBJPLQGSZYQYAXBKYSECJSZNSLYZH",
"ZXLZCGHPXZHZNYTDSBCJKDLZAYFFYDLEBBGQYZKXGLDNDNYSKJSHDLYXBCGHXYPKDJMMZNGMMCLGWZSZXZJFZNMLZZTHCS",
"YDBDLLSCDDNLKJYKJSYCJLKWHQASDKNHCSGAGHDAASHTCPLCPQYBSZMPJLPCJOQLCDHJJYSPRCHNWJNLHLYYQYYWZPTCZG",
"WWMZFFJQQQQYXACLBHKDJXDGMMYDJXZLLSYGXGKJRYWZWYCLZMSSJZLDBYDCFCXYHLXCHYZJQSQQAGMNYXPFRKSSBJLYXY",
"SYGLNSCMHCWWMNZJJLXXHCHSYZSTTXRYCYXBYHCSMXJSZNPWGPXXTAYBGAJCXLYXDCCWZOCWKCCSBNHCPDYZNFCYYTYCKX",
"KYBSQKKYTQQXFCMCHCYKELZQBSQYJQCCLMTHSYWHMKTLKJLYCXWHEQQHTQKZPQSQSCFYMMDMGBWHWLGSLLYSDLMLXPTHMJ",
"HWLJZYHZJXKTXJLHXRSWLWZJCBXMHZQXSDZPSGFCSGLSXYMJSHXPJXWMYQKSMYPLRTHBXFTPMHYXLCHLHLZYLXGSSSSTCL",
"SLDCLRPBHZHXYYFHBMGDMYCNQQWLQHJJCYWJZYEJJDHPBLQXTQKWHLCHQXAGTLXLJXMSLJHTZKZJECXJCJNMFBYCSFYWYB",
"JZGNYSDZSQYRSLJPCLPWXSDWEJBJCBCNAYTWGMPAPCLYQPCLZXSBNMSGGFNZJJBZSFZYNTXHPLQKZCZWALSBCZJXSYZGWK",
"YPSGXFZFCDKHJGXTLQFSGDSLQWZKXTMHSBGZMJZRGLYJBPMLMSXLZJQQHZYJCZYDJWFMJKLDDPMJEGXYHYLXHLQYQHKYCW",
"CJMYYXNATJHYCCXZPCQLBZWWYTWBQCMLPMYRJCCCXFPZNZZLJPLXXYZTZLGDLTCKLYRZZGQTTJHHHJLJAXFGFJZSLCFDQZ",
"LCLGJDJZSNZLLJPJQDCCLCJXMYZFTSXGCGSBRZXJQQCTZHGYQTJQQLZXJYLYLBCYAMCSTYLPDJBYREGKLZYZHLYSZQLZNW",
"CZCLLWJQJJJKDGJZOLBBZPPGLGHTGZXYGHZMYCNQSYCYHBHGXKAMTXYXNBSKYZZGJZLQJTFCJXDYGJQJJPMGWGJJJPKQSB",
"GBMMCJSSCLPQPDXCDYYKYPCJDDYYGYWRHJRTGZNYQLDKLJSZZGZQZJGDYKSHPZMTLCPWNJYFYZDJCNMWESCYGLBTZZGMSS",
"LLYXYSXXBSJSBBSGGHFJLYPMZJNLYYWDQSHZXTYYWHMCYHYWDBXBTLMSYYYFSXJCBDXXLHJHFSSXZQHFZMZCZTQCXZXRTT",
"DJHNRYZQQMTQDMMGNYDXMJGDXCDYZBFFALLZTDLTFXMXQZDNGWQDBDCZJDXBZGSQQDDJCMBKZFFXMKDMDSYYSZCMLJDSYN",
"SPRSKMKMPCKLGTBQTFZSWTFGGLYPLLJZHGJJGYPZLTCSMCNBTJBQFKDHBYZGKPBBYMTDSSXTBNPDKLEYCJNYCDYKZTDHQH",
"SYZSCTARLLTKZLGECLLKJLQJAQNBDKKGHPJTZQKSECSHALQFMMGJNLYJBBTMLYZXDXJPLDLPCQDHZYCBZSCZBZMSLJFLKR",
"ZJSNFRGJHXPDHYJYBZGDLQCSEZGXLBLGYXTWMABCHECMWYJYZLLJJYHLGNDJLSLYGKDZPZXJYYZLWCXSZFGWYYDLYHCLJS",
"CMBJHBLYZLYCBLYDPDQYSXQZBYTDKYXJYYCNRJMPDJGKLCLJBCTBJDDBBLBLCZQRPYXJCJLZCSHLTOLJNMDDDLNGKATHQH",
"JHYKHEZNMSHRPHQQJCHGMFPRXHJGDYCHGHLYRZQLCYQJNZSQTKQJYMSZSWLCFQQQXYFGGYPTQWLMCRNFKKFSYYLQBMQAMM",
"MYXCTPSHCPTXXZZSMPHPSHMCLMLDQFYQXSZYJDJJZZHQPDSZGLSTJBCKBXYQZJSGPSXQZQZRQTBDKYXZKHHGFLBCSMDLDG",
"DZDBLZYYCXNNCSYBZBFGLZZXSWMSCCMQNJQSBDQSJTXXMBLTXZCLZSHZCXRQJGJYLXZFJPHYMZQQYDFQJJLZZNZJCDGZYG",
"CTXMZYSCTLKPHTXHTLBJXJLXSCDQXCBBTJFQZFSLTJBTKQBXXJJLJCHCZDBZJDCZJDCPRNPQCJPFCZLCLZXZDMXMPHJSGZ",
"GSZZQLYLWTJPFSYASMCJBTZYYCWMYTZSJJLJCQLWZMALBXYFBPNLSFHTGJWEJJXXGLLJSTGSHJQLZFKCGNNNSZFDEQFHBS",
"AQTGYLBXMMYGSZLDYDQMJJRGBJTKGDHGKBLQKBDMBYLXWCXYTTYBKMRTJZXQJBHLMHMJJZMQASLDCYXYQDLQCAFYWYXQHZ",
);
function utf8_to_gbk($string)//编码转换,必须转换成GB2312字符,这里只是简单的判断并不是很准确,可以自己写一个.
{
if (mb_check_encoding($string,'gb2312'))
return $string;
if (function_exists('iconv'))
return iconv("utf-8","gb2312//IGNORE",$string);
return mb_convert_encoding($string,'gb2312','utf-8');
}
function conv($str)
{
$str = self::utf8_to_gbk($str);
$len = strlen($str);
$newStr = '';
for($i=0; $i<$len ; ++$i)
{
$H = ord($str[$i]);
$L = ord($str[$i+1]);
//字符集非法
if ($H < 0xB0 || $L < 0xA1 || $H > 0xF7 || $L == 0xFF)
{
$newStr .= $str[$i];
continue;
}
if ($H < 0xD8)//($H >= 0xB0 && $H <=0xD7)//查询文字在一级汉字区(16-55)
{
$W = ($H << 8) | $L;
foreach(self::$FirstTable as $key=>$value)
{
if ($W < $value)
{
$newStr .= self::$FirstLetter[$key];
break;
}
}
}
else// if (H >= 0xD8 && H <= 0xF7)//查询中文在二级汉字区(56-87)
$newStr .=self::$SecondTable[$H - 0xD8][$L-0xA1];
++$i;
}
return $newStr;
}
}
echo zh2py::conv('Chinese 中华人民共和国');//Chinese ZHRMGHG
]]>比如”中华人民共和国” 是ZHRMGHG
最近在ALMRun程序就用到了这个方法,,顺便写了一下PHP版的.感觉PHP的更简单哈,
适用于要求不是很高的场合,因为这个没有处理多音字,只支持GB2312字符,不过优点就是足够简单,几行代码的问题.有需要的可以拿去用,欢迎报错.
]]>之前一直在使用ALTRun,只是这个好久没有更新了,有一些问题无法实现,所以我就在找同类的软件,
使用过像Launchy,Executor,FindAndRunRobot等软件,但各有各的缺点都不太顺手,直到有一天在GoogleCode上无意中发现了这个软件Merry,看了软件介绍,基本上就是我理想中的样子,很感兴趣就下载来测试了.
Merry 是一个 Merry 命令执行工具。部分功能相似的软件有 Linux 下的gmrun,Windows 下的AutoHotkey或ALTRun等,跨平台软件Launchy(不过 Merry 和它们在定位上有差别)。
为什么开发 Merry
最初使用 Linux 系统非常喜欢 gmrun + openbox 的组合,gmrun 能够弹出一个命令输入窗口,输入程序的名称就可以执行对应的程序,而 openbox 则可以非常方便的进行快捷键的绑定。后来使用 Windows 系统时,一直没有找到类似的替代软件,从而萌发了自己开发一个的想法。简单的制作之后,我开始使用 Merry,经过长时间的使用发现确实带来了很多的便利,致使之后使用没有安装 Merry 的机器时感觉很不习惯,这时候我发现它应该是一个有用的软件,于是有了今天的开源软件 Merry。随着时间的流逝 Merry 已经越来越丰富,而不仅仅只有上述这么简单的功能而已,只要你有想法,Merry 能尽量帮助你实现。
Merry 的目标
在基于窗口的操作系统中,简化一切重复、繁琐的操作并提供一些实用的功能。
Merry 的特点和功能
- 跨平台的支持,让你在所有平台下保持一致的操作方式(目前仅仅实现了 Windows 版本,相信不久之后 Linux 和 MacOS 版就会完成)
- 可以定义 Merry 命令(快捷键)来完成一些常用的操作,例如:打开目录、启动程序、打开网页等
- 通过 Merry 命令可以模拟用户的输入,例如:模拟键盘和鼠标输入
- 通过 Merry 可以轻松的管理窗口,例如:关闭窗口、最大化和还原窗口、移动窗口、隐藏窗口等
- 通过 Merry 命令可以来进行自动化的操作,例如:打开某应用程序,自动输入用户密码进行登录等
- Merry 采用完全开放的体系,可以使用 Lua 的扩展库或者外部程序来扩展 Merry 的功能
其它介绍请移步下面的网址,我就偷懒不写了.
https://code.google.com/p/name5566-merry/
由于原版的功能还不是很完善,而我之前也是习惯使用ALTRun的,所以就尝试修改了一下,之前使用ALTRUN的也可以快速转过来.
修改增强版最主要特点(其它的请看软件目录下的README.MD)
另外这个也是可以作为WIN+R来使用的,比如你并没有添加services.msc命令,这时输入services.msc列表当然是不会有任何显示的,不过按回车之后还是会执行到services.msc的,并且会自动添加到列表中,以后再输入就可以看到了.同样支持按TAB输入参数
因为我是初次接触VC,对VC不熟,修改过程中遇到问题都是从Google找的答案,程序可能会有一些BUG.
我目前已经使用这个替换了ALTRUN,因为ALTRUN能实现的,这个基本上实现了,没实现了我也会根据需求,尽量去实现.
其它的不多说了,不管我觉得如何,适合自己的,用得顺手的才是最好的,各有所好.
有兴趣的可以下载测试,有问题或建议同样欢迎反馈…
截图
选定命令之后按TAB键可以添加参数
在命令列表按Insert键添加新命令
支持拼音首字母识别,比如:列表中有”宽带连接”,可以输入 “kdlj
“
这是根据区位表匹配的,比较节省代码,只支持GB2312字符,也没有处理多音字,碰到多音字,一个不行可以换另一个.如果有兴趣帮助我一起开发的可以联系我,或者直接提交补丁文件给我.
主页地址: http://almrun.chenall.net
更新记录: http://almrun.chenall.net/update_log.html
修改版源码: https://github.com/chenall/ALMRun
更多功能介绍: http://almrun.chenall.net/
扩展功能介绍: https://github.com/chenall/ALMRun/blob/master/doc/config_api.md
注:ALMRun独立主页已经上线,以后请关注ALMRUN主页获取更新。
软件下载:
七牛镜像下载:
]]>之前一直在使用ALTRun,只是这个好久没有更新了,有一些问题无法实现,所以我就在找同类的软件,
使用过像Launchy,Executor,FindAndRunRobot等软件,但各有各的缺点都不太顺手,直到有一天在GoogleCode上无意中发现了这个软件Merry,看了软件介绍,基本上就是我理想中的样子,很感兴趣就下载来测试了.
]]>获取WINDOWS文件的文件名/路径/扩展名
例子:
file="c:\\Windows\\notepad.txt"
FileName = file:match("([^\\]+)$") -- notepad.txt
FilePath = file:sub(1,-FileName:len()-1) -- c:\Windows\
FileExt = FileName:match("%.[^%.]*$") -- .txt
WINDOWS下环境变量扩展
例子:
path = "%WinDir%\\Notepad.exe"
path = path:gsub("%%(%S+)%%",os.getenv) -- C:\Windows\notepad.exe
获取CMD命令输出结果
例子:
local f = io.popen('dir /b /s')
print(f:read("*a") -- 读取所有内容
其中read参数可以如下
使用以下命令可以循环读取每一行.
for line in f:lines() do
print(line)
end
f:lines()也可以用f:read(“*l”)
或用下面语句读取每4个字节
for line in f:read(4) do
print(line)
end
字符串相关操作
a="abcd"
b=3456
print(a..b.."test") ---- abcd3456test
a = "test"
a:len() -- 4 或
string.len(a) -- 4
--也可以直接用 `#`
print(#a) --- 4
a="123456"
a:sub(1,3) 或 string.sub(a,1,3) 下同 --- 123
a:sub(-1) -- 6
a:sub(1,-3) -- 1234
代码在线调试器: http://www.lua.org/cgi-bin/demo
]]>