Loop设备不够导致Xen虚拟机启动失败

今天,在管理Xen虚拟机的时候遇到了问题,新建了一台虚拟机后无法启动安装系统,查看了Xen的日志,以及手动启动的时候,都有如下错误:
Error: Device 5632 (vbd) could not be connected. /etc/xen/scripts/block failed; error detected.
这错误,让我直接摸不着头脑,于是修改设置继续启动尝试,突然发现,在没加载ISO镜像文件的时候,居然能启动,脑子里一个念头闪过,莫非是镜像文件的问题,导致无法加载? 继续阅读

发表在 Linux Tips, 虚拟化技术 | 标签为 , , | 2 条评论

libvirt API获得Xen虚拟机CPU使用率

最近在用Nagios监控Xen PV虚拟机的时候出现了问题,在被监控的服务器上是采用nrpe来采集数据的。但是在进程里无法看到PV虚拟机的进程,虽然可以通过xm top vpsname的方式来获取名为vpsname虚拟机的cpu使用率情况,但是不便于采集数据,通过xm list可以采集到cpu时间,根据CPU时间的差值,可以计算CPU使用率,可是该命令只能root执行,因为该命令可以进行关闭,重启虚拟机等重要操作,所以如果把权限给了nrpe,将可能造成严重的安全问题。
幸好livirt提供了API,所以我打算尝试用API写一个Nagios的插件来满足的我的需求,我的想法就是分别2次获得虚拟机的CPU时间,并分别记录2次取得数据时的系统时间,然后根据差值来计算,在理论上是存在一些误差的。

1.要使用API,首先需要安装libvirt-devel

[root@test ~]# yum -y install libvirt-devel

2.我的代码如下,文件名为vCpu.c

/**
 * Program Name: vCpu.c
 * Author: steptodream
 * Description:A simple plugin to get vps cpu usage
 *             for nagios(nrpe) by libvirt api
 * Compile:gcc -o vCpu vCpu.c -lvirt
 */
#include <stdlib .h>
#include <stdio .h>
#include <libvirt /libvirt.h>

/* define the exit status for nagios */
#define OK       0
#define WARNING  1
#define CRITICAL 2
#define UNKNOWN  3

/* get cpu time of the given name */
double getCpuTime(char *vpsName,virConnectPtr conn) {
    virDomainInfo info;
    virDomainPtr domain = NULL;
    int ret;

    /* Find the domain of the given name */
    domain = virDomainLookupByName(conn, vpsName);
    if (domain == NULL) {
        printf("Failed to find the vps called %s\n", vpsName);
        exit(OK);
    }

    /* Get the information of the domain */
    ret = virDomainGetInfo(domain, &info);
    virDomainFree(domain);

    if (ret < 0) {
        printf("Failed to get information for %s\n", vpsName);
        exit(OK);
    }

    return info.cpuTime;
}

int main(int argc,char * argv[])
{
    char *vpsName;             /* vps name */
    int  interval = 1;         /* check interval */
    double warning;            /* warning value */
    double critical;           /* critical value */
    double cpuUsage;           /* cpu usage of the vps */
    struct timeval startTime;  /* time of the first time to get cpu time */
    struct timeval endTime;    /* time of the second time to get cpu time */
    int realTime;              /* real interval between two times */
    long long startCpuTime;    /* cpu time of the first time */
    long long endCpuTime;      /* cpu time of the second time */
    int  cpuTime;              /* value of startCpuTime - endCpuTime */
    char *output;              /* output data for nagios */
    int  ret;                  /* exit status for nagios */
    virConnectPtr conn;        /* connection pointer */

    switch (argc){
        case 5:
             interval = atoi(argv[4]);
        case 4:
             vpsName  = argv[1];
             warning  = atof(argv[2]);
             critical = atof(argv[3]);
             break;
        default:
             printf("Usage:vCpu <vName> <warning> <critical> [interval]\n\n");
             return OK;
    }

    /* connect to local Xen Host */
    conn = virConnectOpenReadOnly(NULL);
    if (conn == NULL) {
        printf("Failed to connect to local Xen Host\n");
        return OK;
    }

    /* get cpu time the first time */
    startCpuTime = getCpuTime(vpsName, conn);

    /* get start time */
    if (gettimeofday(&startTime, NULL) == -1) {
        printf("Failed to get start time\n");
        return OK;
    }

    /* wait for some seconds  */
    sleep(interval);

    /* get cpu time the second time */
    endCpuTime = getCpuTime(vpsName, conn);

    /* get end time */
    if (gettimeofday(&endTime, NULL) == -1) {
        printf("Failed to get end time\n");
        return OK;
    }

    /* colose connection */
    virConnectClose(conn);

    /* calculate the usage of cpu */
    cpuTime = (startCpuTime - endCpuTime) / 1000;
    realTime = 1000000 * (startTime.tv_sec - endTime.tv_sec) +
        (startTime.tv_usec - endTime.tv_usec);
    cpuUsage = cpuTime / (double)(realTime);

	/* display cpuUsage by percentage */
	cpuUsage *= 100;

    /* make output data and exit status for nagios*/
    if (cpuUsage > critical) {
        output = "CRITICAL";
        ret    = CRITICAL;
    } else if (cpuUsage > warning){
        output = "WARNING";
        ret    = WARNING;
    } else {
        output = "OK";
        ret    = OK;
    }
    printf("%s CPU:%.2f%|CPU=%.2f",output,cpuUsage,cpuUsage);

    return ret;
}

继续阅读

发表在 Linux基础, 开源工具使用, 系统监控 | 标签为 , , , , | 留下评论

Perl通过Socks代理发送邮件

前段时间写了一篇关于Perl发送邮件的博客,有读者联系我说,希望能通过Socks代理的方式发送,并给了我一些参考文件,今天抽空测试了一下,要使用Socks代理连接,我们需要Net::SOCKS这个模块,基本代码如下。

#!/usr/bin/perl -w
use strict;
use Net::SMTP_auth;
use Net::SOCKS;

#smtp邮件服务器和端口
my $smtpHost = 'smtp.163.com';
my $smtpPort = '25';
my $sslPort = '465';

#auth info to connect socks server
my $socksServer = 'x.x.x.x';
my $socksUser   = 'username';
my $socksPass   = 'password';
my $socksPort   = '1080';

#smtp服务器认证用户名密码(就是你登陆邮箱的时候的用户名和密码)
my $username = 'user@163.com';
my $passowrd = 'password';

#邮件来自哪儿,要去哪儿,邮件标题
my $from = 'from@163.com';
my $to   = 'to@somedomain.com';
my $subject = '[Notice]TEST MAIL';

#设置邮件header
my $header = << "MAILHEADER";
From:$from
To:$to
Subject:$subject
Mime-Version:1.0
Content-Type:text/plain;charset="UTF-8"
Content-Trensfer-Encoding:7bit

MAILHEADER

#设置邮件内容
my $message = << "MAILBODY";
TEST MAILBODY
MAILBODY

#获得邮件域名部分,用于连接的时候表名身份
my @helo = split /\@/,$from;

#连接到socks服务器
my $sock = new Net::SOCKS(socks_addr => $socksServer,
                socks_port => $socksPort,
                user_id => $socksUser,
                user_password => $socksPass,
                protocol_version => 5);

#通过socks代理与smtp服务器建立连接
my $sockfd = $sock->connect(
		peer_addr => $smtpHost,
		peer_port => $smtpPort
) || die "通过Socks代理连接到$smtpHost失败!";

#通过socks代理与smtp的连接句柄,与smtp服务器通信并验证用户
my $smtpHandle = Net::SMTP_auth->new_from_fd(
                $sockfd,
                'r+'
                ) or die("Error:拷贝连接handle失败!");
$smtpHandle->getline();
$smtpHandle->hello($helo[1]);
$smtpHandle->auth('LOGIN',$username,$passowrd) or die("Error:认证失败!");

#发送邮件
$smtpHandle->mail($from);
$smtpHandle->to($to);
$smtpHandle->data();
$smtpHandle->datasend($header);
$smtpHandle->datasend($message);
$smtpHandle->dataend();
$smtpHandle->quit();

print "OK";
$sock->close();
exit 0;
发表在 Linux Tips, Linux基础, Perl相关 | 标签为 , , , | 留下评论

Python发送邮件

上一篇介绍了Perl发送邮件的方法,接下来我们看看同样的例子,如何使用Python发送邮件,这里给出简单的代码,需要你自己根据需求去完善。

#!/usr/bin/python
import smtplib
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email.Header import Header

#发送邮件的相关信息,根据你实际情况填写
smtpHost = 'smtp.163.com'
smtpPort = '25'
sslPort  = '465'
fromMail = 'user@163.com'
toMail   = 'user@somedomain.com'
username = 'user@163.com'
password = 'password'

#邮件标题和内容
subject  = u'[Notice]hello'
body     = u'hello,this is a mail from ' + fromMail

#初始化邮件
encoding = 'utf-8'
mail = MIMEText(body.encode(encoding),'plain',encoding)
mail['Subject'] = Header(subject,encoding)
mail['From'] = fromMail
mail['To'] = toMail
mail['Date'] = formatdate()

try:
	#连接smtp服务器,明文/SSL/TLS三种方式,根据你使用的SMTP支持情况选择一种
	#普通方式,通信过程不加密
	smtp = smtplib.SMTP(smtpHost,smtpPort)
	smtp.ehlo()
	smtp.login(username,password)

	#tls加密方式,通信过程加密,邮件数据安全,使用正常的smtp端口
	#smtp = smtplib.SMTP(smtpHost,smtpPort)
	#smtp.ehlo()
	#smtp.starttls()
	#smtp.ehlo()
	#smtp.login(username,password)

	#纯粹的ssl加密方式,通信过程加密,邮件数据安全
	#smtp = smtplib.SMTP_SSL(smtpHost,sslPort)
	#smtp.ehlo()
	#smtp.login(username,password)

	#发送邮件
	smtp.sendmail(fromMail,toMail,mail.as_string())
	smtp.close()
	print 'OK'
except Exception:
	print 'Error: unable to send email'

继续阅读

发表在 Python相关 | 标签为 , , , , | 2 条评论

Perl发送邮件

本文简单的介绍一下使用Perl发送邮件的方法,我们以使用163的SMTP服务器来发送邮件为例,因为需要用户验证,所以前提是我们有163的邮件账户。如果代码中使用到的Perl模块你没有安装,那么执行的时候就会报错,关于Perl模块的安装方法,参照这里

#!/usr/bin/perl -w
use strict;
use Net::SMTP_auth;

#smtp邮件服务器和端口
my $smtpHost = 'smtp.163.com';
my $smtpPort = '25';
my $sslPort = '465';

#smtp服务器认证用户名密码(就是你登陆邮箱的时候的用户名和密码)
my $username = 'user@163.com';
my $passowrd = 'password';

#邮件来自哪儿,要去哪儿,邮件标题
my $from = 'user@163.com';
my $to   = 'to@somedomain.com';
my $subject = '[Notice]测试邮件';

#设置邮件header
my $header = < < "MAILHEADER";
From:$from
To:$to
Subject:$subject
Mime-Version:1.0
Content-Type:text/plain;charset="UTF-8"
Content-Trensfer-Encoding:7bit

MAILHEADER

#设置邮件内容
my $message = << "MAILBODY";
在这里写邮件的内容。
你好,这是来自$from的测试邮件。
MAILBODY

#获得邮件域名部分,用于连接的时候表名身份
my @helo = split /\@/,$from;

#连接smtp服务器,明文/SSL/TLS三种方式,根据你使用的SMTP支持情况选择一种
#后2种暂时被我注释了,两个=cut之间的就是被注释的
#普通方式,通信过程不加密
my $smtp = Net::SMTP_auth->new(
                "$smtpHost:$smtpPort",
                Hello   => $helo[1],
                Timeout => 30
                ) or die("Error:连接到$smtpHost失败!");
$smtp->auth('LOGIN',$username,$passowrd) or die("Error:认证失败!");

=cut
#tls加密方式,通信过程加密,邮件数据安全,使用正常的smtp端口
use Net::SMTP::TLS;
my $smtp = Net::SMTP::TLS->new(
                "$smtpHost:$smtpPort",
                User     => $username,
                Password => $passowrd,
				Hello    => $helo[1],
                Timeout  => 30
                ) or die "Error:通过TLS连接到$smtpHost失败!";

#纯粹的ssl加密方式,通信过程加密,邮件数据安全
use Net::SMTP::SSL;
my $smtp = Net::SMTP::SSL->new(
                "$smtpHost:$sslPort",
                Hello   => $helo[1],
                Timeout => 30
                ) or die "Error:通过SSL连接到$smtpHost失败!";
$smtp->auth($username,$passowrd) or die("Error:认证失败!");
=cut

#发送邮件
$smtp->mail($from);
$smtp->to($to);
$smtp->data();
$smtp->datasend($header);
$smtp->datasend($message);
$smtp->dataend();
$smtp->quit();

print "OK";
exit 0;

继续阅读

发表在 Perl相关 | 标签为 , , , , , , | 留下评论

Inotify文件监控

最近遇到了监控日志文件实时变化的需求,我使用Perl的Linux::Inotify2模块来实现的,简单介绍一下这个模块的使用方法。
比如我们要监控文件被修改事件,捕获到事件后,就创建子进程去执行一些我们需要的操作,这里我给出最基本的代码。 继续阅读

发表在 Perl相关 | 标签为 , , , | 留下评论

Perl实现ssh自动登录

一,基于单纯的密码验证的情况:
1.安装Net::SSH::Perl模块,安装方法参照Perl模块安装
2.自动登录例子,我要用testuser用户登陆到服务器192.168.0.100执行df命令:

#!/usr/bin/perl -w
use strict;
use Net::SSH::Perl;

my $host = '192.168.0.100';
my $user = 'testuser';
my $password = '123456';

my $ssh = Net::SSH::Perl->new($host);
$ssh->login($user,$password);
my ($stdout,$stderr,$exit) = $ssh->cmd("df -h");
$ssh->cmd("exit");
if($stderr){
   print "ErrorCode:$exit\n";
   print "ErrorMsg:$stderr";
} else {
   print $stdout;
}
exit $exit;

继续阅读

发表在 Linux Tips, Perl相关 | 标签为 , , , | 留下评论

Perl模块安装

一般来说,安装perl模块常见有源码、CPAN命令、包管理工具等三种方法,本文以安装Net::Telnet模块为例,简单的介绍一下这三种方法。

第一种,直接去CPAN官网下载源码包安装,详细的安装方法等,请参照解压目录下的README或者INSTALL文件:

[root@test ~]# wget http://search.cpan.org/CPAN/authors/id/J/JR/JROGERS/Net-Telnet-3.03.tar.gz
[root@test ~]# tar -xzvf Net-Telnet-3.03.tar.gz
[root@test ~]# cd Net-Telnet-3.03
[root@test Net-Telnet-3.03]# perl Makefile.PL
[root@test Net-Telnet-3.03]# make && make test
[root@test Net-Telnet-3.03]# make install

继续阅读

发表在 Linux Tips, Perl相关 | 标签为 , , , | 留下评论

Nginx+Apache配置

我们依然尽可能采用yum来安装我们需要的软件,由系统官方维护的软件,其安全性和稳定性都值得信赖,并且容易管理,升级方便,但是在CentOS和RHEL的官方yum源中暂时没有Nginx等软件包,所以我们需要使用EPEL的yum源。EPEL是什么,EPEL的yum源怎么添加,点击这里查看。

本文将要介绍的Nginx+Apache结构,其实就是Nginx做前端,Apache做后端,充分发挥他们各自的优势之处。Nginx对于高并发性能出众,Proxy功能强效率高,占用系统资源少,而Apache在高并发时对队列的处理比FastCGI(Nginx需要通过fastcgi等方式运行php)更好,并且在处理动态php页面时,mod_php也比php-cgi更稳定更高效。 继续阅读

发表在 Web服务器, 服务器配置 | 标签为 , , , , , | 3 条评论