Xi's profile风中的甜椒PhotosBlogListsMore ![]() | Help |
|
|
March 12 shell 备忘13.2.3 Shell 参数几个需要记住的特殊参数: $0 = shell 名称或 shel 脚本名称
$1 = 第一个(1)shell 参数
...
$9 = 第九个(9)shell 参数
$# = 位置参数的个数
"$*" = "$1 $2 $3 $4 ... $n"
"$@" = "$1" "$2" "$3" "$4" ... "$n"
$? = 最近执行的命令的退出状态
$$ = 当前 shell 脚本的 PID
$! = 最近启动的后台作业的 PID
需要记住的基本扩展参数: 形式 如果设置了 var 如果没有设置 var
${var:-string} $var string
${var:+string} string null
${var:=string} $var string
(并且执行 var=string)
${var:?string} $var (返回 string 然后退出)
在此,冒号“:”在所有运算表达式中事实上均是可选的。
需要记住的替换参数: 形式 结果
${var%suffix} 删除位于 var 结尾的 suffix 最小匹配模式
${var%%suffix} 删除位于 var 结尾的 suffix 最大匹配模式
${var#prefix} 删除位于 var 开头的 prefix 最小匹配模式
${var##prefix} 删除位于 var 开头的 prefix 最大匹配模式
13.2.4 Shell 重定向需要记住的基本重定向(redirection)运算符(在此[n]表示定义文件描述符的可选参数): [n]> file 重定向标准输出(或 n)到 file。
[n]>> file 重定向标准输出(或 n)到 file。
[n]< file 将file重定向到标准输入(或 n)。
[n1]>&n2 重定向标准输出(或 n1) 到n2。
2> file >&2 重定向标准输出和错误输出到 file。
| command 将标准输出通过管道传递给 command。
2>&1 | command 将标准输出或错误输出通过管道传递给 command。
在这里:
shell 允许你通过使用 $ echo Hello >foo
$ exec 3<foo 4>bar # 打开文件
$ cat <&3 >&4 # 重定向标准输入到 3,标准输出到 4
$ exec 3<&- 4>&- # 关闭文件
$ cat bar
Hello
在这里, n<&- 和 n>&- 表示关闭文件描述符 n。 13.2.5 Shell 条件表达式每条命令均可返回一个退出状态,这个状态值可用于条件表达式:
注意该用法,返回值0用来表示“true”与计算机其它领域中常见的转换是不同的。另外`['等阶于使用 需要记住的常用基本条件表达式: command && if_success_run_this_command_too || true
command || if_not_success_run_this_command_instead
if [ conditional_expression ]; then
if_success_run_this_command
else
if_not_success_run_this_command
fi
当 shell 使用 -e 调用的时候, 需要使用 || true 来确保这个 shell 不会在本行意外退出。 在条件表达式中使用的文件比较运算符有: -e file file 存在则返回True。
-d file file 存在且是一个目录则返回 True。
-f file 如果 file 存在且是一个普通文件则返回 True。
-w file 如果 file 存在且可写则返回 True。
-x file 如果 file 存在且可执行则返回 True。
file1 -nt file2 如果 file1 比 file2 新则返回 True。(指修改日期)
file1 -ot file2 如果 file1 比 file2 旧则返回 True。(指修改日期)
file1 -ef file2 如果两者是相同的设备和具有相同的结点(inode)数则返回 True。
条件表达式中使用的字符串比较运算符有: -z str 如果 str 长度为零则返回 True。
-n str 如果 str 长度为非零则返回 True。
str1 == str2 如果字符串相等则返回 True。
str1 = str2 如果字符串相等则返回 True。
(使用"=="代替"="符合严格意义上的 POSIX 兼容)
str1 != str2 如果字符串不相等则返回 True。
str1 < str2 如果 str1 排在 str2 之前则返回 True(与当前位置有关)。
str1 > str2 如果 str1 排在 str2 之后则返回 True(与当前位置有关)。
条件表达式中的算术整数比较运算符有-eq、-ne、-lt、-le、-gt和-ge。 13.2.6 命令行处理shell按如下的方式处理脚本:
循环 在双单号内单引号将失效。 在 shell 里执行 set -x 或者使用 -x 选项调用 shell,该 shell 将会显示出所有执行的命令。 这对调试非常有用。 March 02 Linux 关于动态链接库以及静态链接库的一些概念库有动态与静态两种
动态通常用.so为后缀,静态用.a为后缀。例如:libhello.so libhello.a 为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。 ln -s libhello.so.1.0 libhello.so.1 ln -s libhello.so.1 libhello.so 使用库
当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。然而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记‘指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。 现在假设有一个叫hello的程序开发包,它提供一个静态库libhello.a 一个动态库libhello.so,一个头文件hello.h,头文件中提供sayhello()这个函数 /* hello.h */ void sayhello(); 另外还有一些说明文档。 这一个典型的程序开发包结构 1.与动态库连接 linux默认的就是与动态库连接,下面这段程序testlib.c使用hello库中的sayhello()函数 /*testlib.c*/ #include #include int main() { sayhello(); return 0; } 使用如下命令进行编译 $gcc -c testlib.c -o testlib.o 用如下命令连接: $gcc testlib.o -lhello -o testlib 在连接时要注意,假设libhello.o 和libhello.a都在缺省的库搜索路径下/usr/lib下,如果在其它位置要加上-L参数 与与静态库连接麻烦一些,主要是参数问题。还是上面的例子: $gcc testlib.o -o testlib -WI,-Bstatic -lhello 注:这个特别的"-WI,-Bstatic"参数,实际上是传给了连接器ld. 指示它与静态库连接,如果系统中只有静态库当然就不需要这个参数了。 如果要和多个库相连接,而每个库的连接方式不一样,比如上面的程序既要和libhello进行静态连接,又要和libbye进行动态连接,其命令应为: $gcc testlib.o -o testlib -WI,-Bstatic -lhello -WI,-Bdynamic -lbye 3.动态库的路径问题 为了让执行程序顺利找到动态库,有三种方法: (1)把库拷贝到/usr/lib和/lib目录下。 (2)在LD_LIBRARY_PATH环境变量中加上库所在路径。例如动态库libhello.so在/home/ting /lib目录下,以bash为例,使用命令: $export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ting/lib (3) 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见、 4.查看库中的符号 有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种,一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所谓的“弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。例如,假设开发者希望知道上央提到的hello库中是否定义了 printf(): $nm libhello.so |grep printf U printf U表示符号printf被调用,但是并没有在函数内定义,由此可以推断,要正常使用hello库,必须有其它库支持,再使用ldd命令查看hello依赖于哪些库: $ldd hello libc.so.6=>/lib/libc.so.6(0x400la000) /lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000) 从上面的结果可以继续查看printf最终在哪里被定义. linux静态链接库与动态链接库一、引言 通常情况下,对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下。所以这些函数库被成为静态库(static libaray),通常文件名为“libxxx.a”的形式。 其实,我们也可以把对一些库函数的链接载入推迟到程序运行的时期(runtime)。这就是如雷贯耳的动态链接库(dynamic link library)技术。 二、动态链接库的特点与优势 首先让我们来看一下,把库函数推迟到程序运行时期载入的好处: 1. 可以实现进程之间的资源共享。 什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。 2. 将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。 3. 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。 程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。 三、动态链接库的创建 由于动态链接库函数的共享特性,它们不会被拷贝到可执行文件中。在编译的时候,编译器只会做一些函数名之类的检查。在程序运行的时候,被调用的动态链接库函数被安置在内存的某个地方,所有调用它的程序将指向这个代码段。因此,这些代码必须实用相对地址,而不是绝对地址。在编译的时候,我们需要告诉编译器,这些对象文件是用来做动态链接库的,所以要用地址不无关代码(Position Independent Code (PIC))。 对gcc编译器,只需添加上 -fPIC 标签,如: gcc -fPIC -c file1.c 注意到最后一行,-shared 标签告诉编译器这是要建立动态链接库。这与静态链接库的建立很不一样,后者用的是 ar 命令。也注意到,动态链接库的名字形式为 “libxxx.so” 后缀名为 “.so” 四、动态链接库的使用 使用动态链接库,首先需要在编译期间让编译器检查一些语法与定义。 这与静态库的实用基本一样,用的是 -Lpath 和 -lxxx 标签。如: gcc file1.o file2.o -Lpath -lxxx -o program.exe 编译器会先在path文件夹下搜索libxxx.so文件,如果没有找到,继续搜索libxxx.a(静态库)。 在程序运行期间,也需要告诉系统去哪里找你的动态链接库文件。在UNIX下是通过定义名为 LD_LIBRARY_PATH 的环境变量来实现的。只需将path赋值给此变量即可。csh 命令为: setenv LD_LIBRARY_PATH your/full/path/to/dll 一切安排妥当后,你可以用 ldd 命令检查是否连接正常。 ldd program.exe 动态链接库*.so的编译与使用 动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前一直不太了解得东东,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。 下面通过一个例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。 so_test.h: test_a.c: test_b.c: test_a.c: 将这几个文件编译成一个动态库:libtest.so $ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so 2、动态库的链接
在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c。
test.c:
#include "so_test.h" int main() { test_a(); test_b(); test_c(); return 0; } 将test.c与动态库libtest.so链接生成执行文件test:
$ gcc test.c -L. -ltest -o test 测试是否动态连接,如果列出libtest.so,那么应该是连接正常了
$ ldd test 执行test,可以看到它是如何调用动态库中的函数的。
3、编译参数解析
最主要的是GCC命令行的一个选项: -shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件 -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。 -L.:表示要连接的库在当前目录中 -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称 LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。
4、注意
调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。 May 01 FTP命令批量自动下载使用FTP下载目录,即FTP命令批量自动下载的bat文件
该文章转载自1024k:http://www.1024k.cn/os/2007/200704/20692.html FTP不支持目录的下载,不过FTP命令提供了mget命令,允许多文件下载,但每下载一个文件都需要确认,不能自动完成。本文主要介绍使用批处理,结合FTP的相关命令来实现批量文件的下载,以便达到目录下载的目的。
大致想法如下: ftp -s:filename hosts >result.txt 执行脚本,并将结果定向输出到result.txt
脚本内容,如 cd mydir ls bye 可以将mydir命令列出 然后使用批处理分析result.txt 从150 Opening ASCII mode data connection for file list.的下一行开始算,直到226 Transfer complete都是要下载的内容 然后用批处理加ftp脚本,使用get命令逐个下载 但实际过程中发现,在FTP脚本中使用get有问题,提示参数错误,无法使用。 查看了ftp的帮助ftp -?
G:>ftp -?
Transfers files to and from a computer running an FTP server service
(sometimes called a daemon). Ftp can be used interactively. FTP [-v] [-d] [-i] [-n] [-g] [-s:filename] [-a] [-w:windowsize] [-A] [host]
-v Suppresses display of remote server responses.
-n Suppresses auto-login upon initial connection. -i Turns off interactive prompting during multiple file transfers. -d Enables debugging. -g Disables filename globbing (see GLOB command). -s:filename Specifies a text file containing FTP commands; the commands will automatically run after FTP starts. -a Use any local interface when binding data connection. -A login as anonymous. -w:buffersize Overrides the default transfer buffer size of 4096. host Specifies the host name or IP address of the remotehost to connect to. Notes:
- mget and mput commands take y/n/q for yes/no/quit. - Use Control-C to abort commands. 发现 -i 参数可以去除mget的提示,经过测试,实现了如下脚本(使用了匿名登入,如果非匿名,可以修改登入脚本): echo cd autoruns>ftp.txt
echo mget *>>ftp.txt echo bye>>ftp.txt ftp -i -A -s:ftp.txt 10.1.103.10 不过,这只是下载了目录中的文件,如果有子目录,那还需要用dir命令输出,并转向输出到文本,用find来提取目录,如: echo cd autoruns>ftp.txt
echo dir>>ftp.txt echo bye>>ftp.txt ftp -A -s:ftp.txt 10.1.103.10 |find "<DIR>">result.txt for /f "tokens=2,3*" %%i in (result.txt) do echo %%k 如有子文件夹,那就要深入编写了。 经过编写测试,实现如下脚本,运行环境WINXP SP2,运行通过,未载其它系统上测试过:
1、主要脚本ftpget.bat,更改前4个变量的相关信息,该脚本调用makeTree.bat,请参见2
rem FTP服务器地址
set host=10.1.103.10 rem FTP登入名,如果匿名不用改
set user=anonymous rem FTP登入密码,如果匿名不用改
set pass=123456 rem 需要下载的FTP目录,如果下载子目录以分格
set dirname=目录1子目录 set homedir=%cd%
rem 生成FTP目录结构
del tree.txt start /w cmd /c makeTree %dirname% 0 del result*.txt for /f "delims=/" %%i in (tree.txt) do (
rem 获取dirname的所有文件
rem ============================= cd %homedir% md %%i cd /d %%i echo %user%>ftp.t xt
echo %pass%>>ftp.txt echo cd %%i>>ftp.txt rem mget *.* 下载所有文件,但不能下载无扩展名的文件;
rem 如果使用mget * 可以下载所有文件,但会把子目录的文件也下载过来 echo mget *.*>>ftp.txt )
cd %homedir% del tree.txt 2、maketree.bat,生成FTP目录树 rem 生成FTP目录结构
rem 调用方法 maketree dir1dir2 n (n>=1) rem %1 == dir1dir2 rem %2 == n set /a treetime=%2+1
echo %1 >>tree.txt echo %user% >ftp%treetime%.txt
echo %pass% >>ftp%treetime%.txt echo cd %1 >>ftp%treetime%.txt echo dir >>ftp%treetime%.txt echo bye >>ftp%treetime%.txt ftp -A -s:ftp%treetime%.txt %host% |find "<DIR>">result%treetime%.txt for /f "tokens=2,3*" %%i in (result%treetime%.txt) do (start /w cmd /c Maketree.bat %1%%k %treetime%) del result%treetime%.txt del ftp%treetime%.txt 虽然已经实现,但仍然有小问题,就是mget *.* 不能下载无扩展名的程序;如果使用mget * 可以下载所有文件,但会把子目录的文件也下载过来。get在FTP脚本中出错也不知为何。 January 15 George, an Artificial Intelligence Avatar
November 20 解决WINSOCKS2的怪问题 (转载)某台笔记本,ewido杀过木马后,就不正常了,具体表现虽然能PING通,但是在过程中会有点不同
c:\>ping 10.0.0.1
Pinging ? with 32 bytes of data:
Reply from 10.0.0.1: bytes=32 time=12ms TTL=255
Reply from 10.0.0.1: bytes=32 time=12ms TTL=255 Reply from 10.0.0.1: bytes=32 time=12ms TTL=255 Reply from 10.0.0.1: bytes=32 time=12ms TTL=255 问号处本应该是IP
后来才知道可能是杀木马、病毒过程中WINSOCK2被破坏引起的。
MS的解决方法:
症状在尝试使用 Ipconfig 程序释放并更新 IP 地址时,您可能会收到以下错误信息:
An error occurred while renewing interface 'Internet':An operation was attempted on something that is not a socket. 当您启动 Internet Explorer 时,可能会收到以下错误信息:
该页无法显示。 在使用计算机时,可能会收到以下错误信息:
在 IPMONTR.DLL 中初始化函数 INITHELPERDLL 启动失败,错误代码为 10107 此外,您可能没有 IP 地址或自动专用 IP 寻址 (APIPA) 地址,并且可能会收到 IP 数据包,但没有发送它们。当您使用 ipconfig /renew 命令时,可能会收到以下错误信息。 消息 1 An error occurred while renewing interface local area connection:an operation was attempted on something that is not a socket.Unable to contact driver Error code 2. 消息 2
The operation failed since no adapter is in the state permissible for this operation. 消息 3
The attempted operation is not supported for the type of object referenced. 在设备管理器中,当您单击“显示隐藏的设备”时,“非即插即用驱动程序”下面的列表中停用“TCP/IP Protocol Driver”,并收到错误代码 24。当您创建拨号连接时,可能会收到以下错误信息: Error 720:No PPP Control Protocols Configured
原因如果 WinSocks 注册表项损坏,则可能出现这些问题。
解决方案如何确定 Winsock2 注册表项是否损坏要确定症状是否由 Winsock2 注册表项的问题引起,请使用以下方法。方法 1:使用 Netdiag 工具要使用 Netdiag 工具,您必须安装 Microsoft Windows XP 支持工具。为此,请按照下列步骤操作。注意:
方法 2:使用 Msinfo32 程序注意:只有在没有 Windows XP 安装 CD 并且未安装支持工具时,才应使用此方法。
如果列表的内容超过 10 个节,则说明安装了第三方加载项。 如果少于 10 个节,则说明缺少信息。 注意:这些条目所代表的是仅装有 TCP/IP 协议的安装。您可能有一个正在工作的 Winsock,如果安装了另一个协议,则可能会看到其他条目。例如,如果安装 NWLink IPX/SPX,您将另外看到 7 个节,也就是总共 17 个节。下面的示例展示了一个新的节标头: MSAFD nwlnkipx [IPX] 通过安装 NWLink IPX/SPX 创建的每个新节也以“MSAFD”开头。因此,仍然只有两个不以这些字母开头的节。 如果 Netdiag 测试失败,或者,如果通过查看 Msinfo32 信息确定了 Winsock 的损坏,您必须使用下一部分的步骤修复 Winsock2 注册表项。 如何恢复损坏的 Winsock2带 Service Pack 2 的 Windows XP要在安装了 Windows XP Service Pack 2 (SP2) 的情况下修复 Winsock,请在命令提示符处键入 netsh winsock reset,然后按 Enter。注意:运行此命令后请重新启动计算机。此外,对于运行 Windows XP SP2 的计算机,还有一个新的 netsh 命令可用于重新构建 Winsock 注册表项。有关更多信息,请访问下面的网站: http://www.microsoft.com/china/technet/prodtechnol/winxppro/maintain/sp2netwk.mspx (http://www.microsoft.com/china/technet/prodtechnol/winxppro/maintain/sp2netwk.mspx) 警告:在运行 netsh winsock reset 命令时,访问或监视 Internet 的程序(如防病毒程序、防火墙或代理客户端)可能会受到不良影响。如果执行此解决方案后某个程序无法正常工作,请重新安装该程序以恢复功能。注意:如果这些步骤都无法解决问题,请执行下一部分的步骤。 不带 Service Pack 2 的 Windows XP如果要在未安装 Windows XP SP2 的情况下修复 Winsock,请删除损坏的注册表项,然后重新安装 TCP/IP 协议。第 1 步:删除损坏的注册表项警告:如果使用注册表编辑器或其他方法错误地修改了注册表,有可能会导致严重问题。这些问题可能需要重新安装操作系统才能解决。Microsoft 不能保证可以解决这些问题。修改注册表需要您自担风险。有关如何备份注册表的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章: 322756 (http://support.microsoft.com/kb/322756/) 如何在 Windows XP 和 Windows Server 2003 中备份、编辑和还原注册表
第 2 步:安装 TCP/IP
November 17 PBS基本完成至少可以用了,我跑了几天的程序,一切正常。
但是需要注意一些细节,今天重启了一下server导致程序混乱,只好手动del掉,重新run一遍。忘了可以在线配置的。这样应该就没有什么问题了。
下午写个文档,发布一下:) November 15 PBS初见成效终于把PBS配置完毕,昨天用自己的程序测试了一下,到现在还没有出错。
让他go on吧。
但是美中不足的是,PBS不能自动监测cpu的使用情况,如果用户用非PBS的方式提交作业,PBS可能重复提交。很讨厌,这样不能充分利用资源,反而导致速度下降。想个解决的方案吧。
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|