expect在自动化脚本中的应用

自动登录

很多时候,我们都需要通过ssh连到远程主机去执行一些命令或脚本。如果没有配置好公钥验证,必须手动输入密码。面对上百台机器,手动输入将会是一场灾难。

这时expect脚本就能解决这个困境。

这个expect脚本可能如下:

#!/usr/bin/expect --
##########################################################################
# Usage: ssh_expect.sh listorder host username password port
##########################################################################
#!/usr/bin/expect
set LISTORDER [lindex $argv 0]
set HOST [lindex $argv 1]
set NAME [lindex $argv 2]
set PASS [lindex $argv 3]
set PORT [lindex $argv 4]
spawn -noecho /usr/local/bin/ssh2 -q -o StrictHostKeyChecking=no -q -l$NAME -p$PORT $HOST "$LISTORDER"
set timeout 3600
expect {
"Are you sure you want to continue connecting (yes/no)?"
{
send "yesn"
expect "*assword"
send "$PASSn"
}
"*assword:"  { send "$PASSn" }
}
expect eof

用法:

./ssh_expect.sh "/share/exec_something.sh" 172.1.1.1 user_03 user_03_pwd 22

第一个参数是在远端机器所要执行的命令,之后的参数分别是远端IP,用户名,密码,端口

 

 

 

 


suse下nfs配置

安装

启动服务

service portmap start #启动portmap服务
service nfsserver start #启动nfsserver服务
chkconfig portmap on #设置portmap为自启动服务
chkconfig nfsserver start #设置nfsserver为自启动服务

服务端配置

  1. 配置/etc/hosts.allow和/etc/hosts.deny设置访问限制
  2. 编辑/etc/exports
    /home/vls 192.168.111.129(ro)
    <本机共享目录> <可访问IP>(访问权限)
  3. exportfs [-aruv] exportfs来从新扫描一次/etc/exports文件, 不需重启nfs 服务
    参数说明:
    -a: 全部挂载(或者卸载)/etc/exports 文件的设置
    -r: 从新挂载/etc/exports 里设置,此外,同步更新/etc/exports 及/var/lib/nfs/xtab的内容
    -u: 卸载某一目录
    -v: 在导出时,将共享目录显示在屏幕上

客户端配置

service portmap start
mount -t nfs -o rw 192.168.111.128:/home/vls /mnt/home/vls

开机自启动

vi /etc/fstab192.168.111.128:/home/vls /mnt/home/vls nfs rw

使用Detours跟踪WinAPI调用情况

Detours是微软研究院的一个用于hook WinAPI的工具。

安装后安装目录的samples目录里面有很多项目。我们用到的是traceapi和withdll项目。

自定义traceapi

打开traceapi目录里面的_win32.cpp,可以看到已经默认hook了绝大部分的WinAPI。我们可以把大多数注释掉,只保留我们关心的几个函数,免得之后要分析的log过大。

以ReadProcessMemory为例,看看如何自定义trace的结果。在_win32.cpp,关于一个WinAPI函数会有四处地方:

第一处:

 

BOOL (__stdcall * Real_ReadProcessMemory)(HANDLE a0,
                                          LPCVOID a1,
                                          LPVOID a2,
                                          DWORD_PTR a3,
                                          PDWORD_PTR a4)
    = ReadProcessMemory;

第二处:

BOOL __stdcall Mine_ReadProcessMemory(HANDLE a0,
                                      LPCVOID a1,
                                      LPVOID a2,
                                      DWORD_PTR a3,
                                      PDWORD_PTR a4)
{
    _PrintEnter("ReadProcessMemory(%p,%p,%p,%p,%p)n", a0, a1, a2, a3, a4);

    BOOL rv = 0;
    __try {
        rv = Real_ReadProcessMemory(a0, a1, a2, a3, a4);
    } __finally {
        _PrintExit("ReadProcessMemory(,,,,) -> %pn", rv);
    };
    return rv;
}

第三处

ATTACH(&(PVOID&)Real_ReadProcessMemory, Mine_ReadProcessMemory);

第四处

DETACH(&(PVOID&)Real_ReadProcessMemory, Mine_ReadProcessMemory);

如果不想trace某个函数,将第一、第二和第四处注释掉即可。

主要自定义的点在第二处,例如a2是buffer地址,a4是读取的字节数。当真正的ReadProcessMemory读取完毕后,我们就可以用这两个信息来看看究竟读了什么。因此在finally子句可以改成一下这样:

int size = (int) a4;
char buf[MAXBUF];
PrintByte(buf, a2, size);

_PrintExit("ReadProcessMemory(,,,,) -> %p,%p -> %sn", rv, a2, buf);

这里的PrintByte函数是将字节数组转为十六进制字符串。

使用

withdll的使用很简单,看看命令行说明即可。

下载安装打开DbgView。使用withdll启动目标程序并将自定义好的traceapi.dll注入进程,即可在DbgView的窗口里看到traceapi打印的信息了。


Pys60在Windows下的开发环境配置步骤(含模拟器)

先确定你的手机平台版本,例如我的E71是S60 3rd FP(Feature Pack) 1。

下载:
安装:
PC端:
  1. 安装ActivePerl
  2. 安装S60 Platform SDKs for Symbian OS, for C++
  3. 安装PythonForS60
  4. 解压Pys60 SDK里面的epoc32文件夹,覆盖C++ SDK安装目录里面epoc32文件夹
至此,可以在开始菜单找到模拟器来运行,并在“安装”里可找到Python shell,enjoy programmming python in S60!

如果在模拟器运行Python shell出现以下错误信息:“Check if the following components are installed: Python Runtime and PIPS Library”,可以下载Open C/C++ Plug-ins for S60 3rd Edition安装。

一般用PythonForS60里面的Application Packager打包的sis不能用在模拟器里面,可以直接把.py文件放在C++ SDK里面的epoc32winscwcDatapython路径下,然后在模拟器的Python Shell中的”Run script”就可以找到你的.py文件了。这比打包sis安装更方便调试。

ubuntu 安装字体步骤

  1. 拷贝目录到/usr/share/fonts/下
  2. 将字体下所有文件权限设成555
  3. 建立字体缓存
转到字体目录
sudo mkfontscale
sudo mkfontdir
sudo fc-cache -f

nvcc in CUDA 3.0 不支持中文路径

近来发现.cu里面的断点不能命中,初步怀疑是项目属性里面的C/C++->代码生成->运行库 与 Hybird CUDA/C++ Options ->Runtime Library里面两个设置不同导致。有文章说,这两个这是应该是一致的。但我发现只要两个设置一旦相同,就会发生链接错误。

然后重新新建一个项目,惊喜地发现可以命中断点了,一时找不到原因,就把项目复制到原来工作的目录里打算迁移东西过来。经过一阵折腾,诡异地发现在同一个项目里面的两个.cu一个能中断点,一个不能……
偶然进入反汇编窗口仔细观察,发现能调试的.cu对应了一段包含源代码的汇编,不能调试的.cu对应一段汇编。而这段汇编的开头只是路径的一部分。
更发现了生成过程中,出现以下警告:

warning: header name contains characters that cannot be represented in Unicode

马上意识到可能是中文路径的问题。

把项目从没有中文的路径打开,清理,生成。可以命中断点了:)
原来是CUDA3.0里的nvcc还不支持中文路径……

Python函数默认参数的一个小陷阱

def foo(a1, args = []):
    print "args before = %s" % (args)
    args.insert(0, 10)
    args.insert(0, 99999)
    print "args = %s " % (args)

def main():
    foo('a')
    foo('b')

if __name__ == "__main__":
    main()

以上小程序会有如下输出:

args before = []
args = [99999, 10] 
args before = [99999, 10]
args = [99999, 10, 99999, 10] 

按照通常的理解,第二次调用的args应该为默认值[],但为什么会变成上一次的结果呢?

查阅Python manual有如下的说法:

Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that that same “pre-computed” value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. This is generally not what was intended. A way around this is to use None as the default, and explicitly test for it in the body of the function, e.g.:

def whats_on_the_telly(penguin=None):
    if penguin is None:
        penguin = []
    penguin.append("property of the zoo")
    return penguin

至此,原因已经很清楚了:函数中的参数默认值是一个可变的list, 函数体内修改了原来的默认值,而python会将修改后的值一直保留,并作为下次函数调用时的参数默认值