地址端口检测

C/C++, Linux, Unix No Comments »

       有时候我们需要对某些服务器是否可用进行判断,一般可以通过telnet ip  port  的方式来实现,这时如果返回的是Connection refused或是Escape character is ‘^],则表示这个端口是开放的,不过前者拒绝该请求,而后者则可以正常联通。如果我们需要一次性检测一批端口是否开放,这时如果一条条输telnet命令可能就有些累了。下面说一下如何用脚本来实现。

      首先我们需要一个可以探测端口的程序,这个我是用c语言来实现的(参考了网上的代码,如果谁发现可用的命令欢迎告诉我哦),通过编译后就可以运行,不过它只实现扫描一个端口的功能。后面会再介绍个shell脚本来实现多次调用该程序来实现扫描多个地址的目的。

      具体c语言的代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <time.h>
#include <arpa/inet.h>

/* 该代码可以用来测试某个端口是否联通,使用方法 a.out 128.32.171.33 23
*  然后查看$?的值,如果是0,则表示该端口可以联通,否则不可以联通
*  可以和shell脚本结合使用
*  文件名:detect_ip_port.c
*/

int main(int argc, char *argv[])
{
 int fd, retval;
 struct sockaddr_in addr;
 struct timeval timeo = {3, 0};
 char buf[1024];
 int i;
 socklen_t len;
 fd_set set;

 fd = socket(AF_INET, SOCK_STREAM, 0);
 addr.sin_family = AF_INET;
 addr.sin_addr.s_addr = inet_addr(argv[1]);
 addr.sin_port = htons(atoi(argv[2]));
 if ((i=connect(fd, (struct sockaddr*)&addr, sizeof(addr))) == 0)
 {
  close(fd);
  perror("connected success:");
  return 0;
 }
 perror("connected error:");
 close(fd);
 return 1;
}

可以通过执行shell命令,来生成可执行文件:

gcc –o detect_one_addr  detect_ip_port.c

为了实现一次扫描多个地址的目的,我首先采用一个txt文件来保存需要扫描的ip 和port等信息,具体txt的内容大致如下:

192.168.0.1 8000 01 服务器1
192.168.0.2 8000 02 服务器2
192.168.0.3 8000 03 服务器3
192.168.0.4 8000 04 服务器4
192.168.0.5 8000 05 服务器5

其中每一行中包括ip  port  编号  名称,每个字段用空格或tab分隔。在此我们假设该文件名称为:servers.txt

接下来使用shell脚本来实现扫描多个地址的目的:

#!/usr/bin/sh

# file name : detect_all.sh

detect_one_addr()
{
 ip=`echo $line |  awk '{print $1}'`
 port=`echo $line |  awk '{print $2}'`
 entr_no=`echo $line |  awk '{print $3}'`
 entr_name=`echo $line |  awk '{print $4}'`

 ./detect_ip_port $ip $port
 if [ $? == 0 ] ; then
 	echo "$entr_no  $entr_name  is OK"
 else
 	echo "$entr_no $entr_name is Failed"
 fi
}

testfile="servers.txt"
while read -r line
do
    detect_one_addr $line
done < $testfile

然后在命令行中执行detect_all.sh即可实现该扫描的功能。你可能会发现如果某个端口不开放,该程序需要过好长时间才会超时,这个超时时间是由系统来决定的,具体是TCP连接的超时时间,一般不建议修改。我也经常遇到连接一个端口经过好久最后联通的情况,因为首次连接需要进行ARP、或是路由器会帮你建立连接(因为这个连接好久不用可能已经休息了,呵呵),所以耐心等待就好。

PS:经过上述程序可以看出,我们可以通过shell或是其他高级语言,如ruby,perl等来做高级的工作,然后我们用c/c++、java等实现底层的功能,这样可以更有效率的解决问题,充分发挥各个语言的优点

HP-UX 新建用户

Linux, Unix No Comments »

在UNIX下建立用户并不像Linux那么简单,主要是需要创建逻辑卷和文件系统。具体过程如下:


#建立新的逻辑卷

lvcreate -L 2560 -n lvcsspkm /dev/vg00 

fstyp /dev/vg00/lvcsspkm # 查看dev/vg00/lvcsspkm的文件系统类型

#前面记得加r,否则会提示newfs: /dev/vg00/lvcsspkm is not a character device

#下面这一步如果不做,可能发现设备上的文件是其他用户的旧文件

newfs -F vxfs -o largefiles /dev/vg00/rlvcsspkm

mkdir /home/user/csspkm

mount /dev/vg00/lvcsspkm /home/user/csspkm

#下面这一步是为了系统重启时自动挂载分区

vi /etc/fstab

#建立用户,并指定默认home目录和默认群组

useradd -d /home/user/csspkm -G dba csspkm

#更给原来文件夹的所有者,注意用:分隔群组而是:号

chown -R csspkm:dba csspkm

#设置密码,不设置的话不能登录

passwd csspkm

      在建立过程中我查找了hp-unix的参考手册还有网上的一些资料。我发现自己电脑上有我们用的系统和软件的参考手册是很重要的,这样如果生产环境出问题,你才能快速的查找资料,从而做出反应。有时候上互联网并不是一件容易的事情。

fedora下gruff的安装使用

Linux, Ruby, 日志 No Comments »

最近一段时间一直在准备着找工作,学各种东西。期间还是感觉很有收获的,等有时间整理一下然后发布出来。实验室的项目也还在进行,不过我的工作相对少了很多(因为快要毕业了嘛,还是很感激老师能体谅我们的,^_^)。

目前我在项目中的任务是做一个系统的图形界面。当初也不知道怎么想的,竟然想用web形式来实现,也许是为了不让自己之前学的ruby和rails不要白费吧,呵呵。现在想想Web GUI的想法的确挺好的,由于ruby的类库丰富,开发相对还是比较轻松的,不过为了让C++系统和rails的能正常交互消息还是需要学一下http类库libcurl方面的知识(这些知识它的官网上有很多,也很详细)。

由于项目的需要,我们的图形界面上需要显示一些数据的分析图表,使用ruby的gruff工具包可以绘制很好的数据分析图表。下面说下linux环境下gruff的安装和使用,安装过程如下:

1、首先安装ruby-1.8.6环境以及ruby gems,大家可以在网上找相关的教程。

2、安装ImageMagick的库,gruff的运行依赖于这些库

yum install ImageMagick

yum install ImageMagick-devel

3、安装TrueType字体。ImageMagick在画图时需要用到这个库。有些linux版本会默认安装,那样的话大家就可以跳过这步了

wget http://www.osresources.com/files/centos-windows-fonts/msfonts.tbz

mkdir /usr/share/fonts/default/TrueType

tar xvjpf msfonts.tbz -C /usr/share/fonts/default/TrueType/

4、安装 rmagick 的gem包

gem install rmagick

5、安装gruff所需的gem包。gruff包会依赖以下包:json_pure、rubyforge、hoe、rake

gem install gruff

至此gruff就安装完成了。下面介绍一个gruff的代码实例,实例中会绘制一个柱状图,其他类型的图的画法请参考gruff的rdoc文档。

示例代码如下:

require 'rubygems'
require 'gruff'

g = Gruff::Bar.new(600)        # The graph will be 600 pixels wide.
g.bar_spacing = 0.5   # the bars' space
g.title = 'The Nodes\'s Load'
g.theme_37signals        # The best-looking theme, in my options.

load_info_1=[21,3,6,14,7,11,19]   #the data information, you can use you own data here.
load_info_2=[8,27,13,4,9,14,10]

range = (1..7)
g.data('Node 1', range.collect { |x| load_info_1[x-1] })
g.data('Node 2', range.collect { |x| load_info_2[x-1]})

g.labels = {2 => 'n=2', 4 => 'n=4', 6 =>'n=6' }
g.write('load_info_bar.png')

输出结果图片如下:

load_info_bar

可以看出,gruff生成的图片还是挺漂亮的。我这里的数据是自己任意写的,没什么实际的意义。

PS:我个人还是很喜欢Ruby语言的,它的语法优美,代码看起来很像伪代码,很易读;它有丰富的类库,对文本处理的功能很强。大家如果想学一门脚本语言的话建议学习Ruby,可以很好的提高你的工作效率,呵呵

参考资料:

[1]http://hi.baidu.com/rainchen/blog/item/089ef7364497de320a55a9a3.html

[2] Ruby Cookbook:  Recipe 12.4. Graphing Data

Linux程序输入、输出重定向

C/C++, Linux No Comments »

对于输出重定向大家应该都比较了解了,一般都是指把输出重定向到一个文件中,而对于输入重定向一般就不是很常用了。暂时的一个应用就是实现程序的脚本控制,比如你用脚本启动另一个程序,然后又需要给这个启动的程序发送命令,这时就需要采用输入重定向了,这对于一些服务类型的程序还是很有用的。要实现真正意义的输入重定向还是比较麻烦的,需要用到管道。

下面用一个简单的示例来实现程序的输入,输出重定向。

//file_name:shi_li.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>

#define MAX_LINE 80
#define PIPE_STDIN  0
#define PIPE_STDOUT 1

int main(){
 int child_pid;

 char outPath[30];
 strcpy(outPath,"./out.file");

 int pfds[2];
 if (pipe(pfds)== 0){
  child_pid=fork();
  //in child process the return pid==0
  if ( child_pid == 0 ) {

   //input file,may be used later.
   //char inPath[30];
   //strcpy(inPath,"./in.file");

   //int inFd = open(inPath,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR);
   int outFd = open(outPath,O_WRONLY|O_APPEND|O_CREAT,S_IRUSR);

   close(0);
   dup2( pfds[PIPE_STDIN], 0);
   dup2(outFd,1);
   close(pfds[PIPE_STDOUT]);
   execl("./getstring","getstring",NULL);
   printf("start getstring: error!!!");
   exit(1);
          }
  else {

   close(pfds[PIPE_STDIN]);
       char msg[MAX_LINE];
         int b=1;
        for(b=1;b<6;b++){              
           sleep(1);
             sprintf(msg,"2+%d\n",b); 
             write( pfds[PIPE_STDOUT], msg, strlen(msg) );              
                 }
         close(pfds[PIPE_STDOUT]);
         sleep(2);
         printf("all done.\n");
         }
       }
 return 0;
} 

接下来是一个很简单的程序输入:

//file_name: getstring.cpp

#include <unistd.h>
#include <iostream>
using namespace std;

int main(){ 
 string tmp;

 while(cin >> tmp,!cin.eof()){
  if(cin.bad()){  
   cerr<<"io stream error"<<endl;
   exit(1); 
  }
  if(cin.fail()){
   cerr<<"io stream error"<<endl;
   cin.clear(istream::failbit);
   continue;
  }
  //ok to process 
  cout<<"all done well:"<<tmp<<endl;
 }
}

编译并运行:

#g++ -o getstring getstring.cpp
#g++ -o shi_li shi_li.cpp
#./shi_li

上述代码包括两个小程序,getstring简单的接收输入的字符串并在终端上回显。shi_li程序负责启动getstring并把输入重定向到管道,输出重定向到out.file文件。执行代码后我们可以查看out.file文件来获得程序执行的结果。

上述小程序可以用在脚本时对向子程序发送命令,从而完成程序测试的自动化。上述代码只是个demo,如果想在实际测试中可用还需要根据自己的情况进行些许修改。

参考资料:

[1] http://blog.chinaunix.net/u/19573/showart_1225848.html

[2]http://www.opengroup.org/onlinepubs/009695399/

ubuntu下成功安装sfslite

C/C++, Linux No Comments »

之前曾采用MIT的开源chord来开发P2P的系统,由于chord依赖于sfslite的一些库文件,所以需要安装sfslite-0.8.16。自此带来了很多问题,因为sfslite需要gcc-4.1.2才能编译,用最新的gcc-4.3或4.4都会编译失败,而且它好像还和操作系统有关,在fedora 7下可以正常编译。如果您不想使用fedora 7这种老版本的系统那就麻烦了。

最近新安装了ubuntu 10,突然想在ubuntu下尝试一下,这样后续的开发就不用再装fedora 7的虚拟机了,而且也可以方便程序的移植。下面简要介绍安装的过程:

首先安装gcc-4.1.2,具体安装过程参考“在ubuntu中编译、安装gcc 4.1.1过程以及遇到的问题”,上面讲的很详细。主要有一个地方需要注意,gcc-4.1.2依赖texinfo库,默然configure不支持texinfo 4.10+,需要修改configure文件。在其中找到’texinfo[^0-9]*([1-3][0-9]|4\.[2-9]|[5-9])’编辑成’texinfo[^0-9]*([1-3][0-9]|4\.[2-9]|4\.[1-9][0-9]*|[5-9])’后保存,编译通过。[注] 无需修改LD_LIBRARY_PATH变量,在ubuntu下没有这个变量,因为已经被废除了,直接安装好后就可以使用了。

[tips]可以使用ubuntu中自带的 update-alternatives 命令来方便的进行多个gcc版本之间的切换(具体命令使用可以在google上搜)。

接下来就是使用gcc 4.1.2来编译sfslite,首先下载sfslite-0.8.16的tar包。(不要使用sfslite-0.8.17,编译会出错)

然后解压,进入源文件根目录,输入 ./configure –with-sfsmisc (with前是两个-) 只要这一个选项就可以了,不用输–with-dmalloc

接下来如果直接make的话会出错,会提示 unknown sizeof  ucred 。在网上找了很久,终于发现只有在编译时加上-D_GNU_SOURCE才可以。在gcc编译选项中增加 -D_GNU_SOURCE,这需要改makefile文件。具体为async和arpc目录下的Makefile文件中找到“ECFLAGS =” 改为:“ECFLAGS = -D_GNU_SOURCE”

然后编译安装即可。

程序偶然出错绝不是偶然

C/C++, Linux, 日志 1 Comment »

       最近项目的程序完成部分代码,需要进行测试,由于测试需要好几台主机才能进行,由于设备限制,我就先把程序在Elastix Linux(我们实验室服务器的linux版本)和我自己的fedora7下进行测试。在Elastix下可以编译通过,但是在程序运行时一旦收到消息开始处理,程序就会崩溃,并且反馈为 glibc detected *** : free(): invalid pointer 错误。但是因为我在fedora7下该程序可以正常接收和处理消息,当时只是认为是操作系统的问题,也没有太在意。

       今天好不容易装好了几台测试电脑,都是fedora系统的,本来打算晚上把测试的程序装上,然后就OK了,应该不会有什么错的。没想到当在多个fedora下运行该程序进行测试时,对于前面几条消息程序还是可以正常处理的,但是当处理到3,4条消息的时候程序开始提示上面的同样的错误。当时自己花了很长时间来找原因,程序的配置改了又改,但还是没有解决,整的也很郁闷。晚上回去后又继续调试,用gdb加载程序,当程序退出后,查看程序的堆栈信息(输入bt)命令,经过几次尝试后终于发现错误的所在,原来是自己当时初始化一个字符串时分配的空间太小。有点像下面这样:char   tempString[MAX_LENGTH]; tempString[length]=0;但是在程序中没有检查length的大小,如果length>=MAX_LENGTH时就会出现上面的错误。然后修改程序后就一切正常了。 

        看来在程序的世界里没有偶然,只有必然,当程序出错时很可能就是你程序错了,不要报有侥幸的心理,专心的找出错误的根源才是王道 :D

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS 登录