Dec
26

Linux系统编程知识在运维排错中的应用

1.    谁偷了我的磁盘空间?

发现大小为10G的/home分区磁盘空间使用了9.8G,但是通过du得到的大小却是5G. 另外的4.8G空间哪里去了呢?

df -Th /home

Filesystem    Type    Size  Used Avail Use% Mounted on

/dev/sda3      ext3     10G   9.8G  0.2G  98% /home

du -hs /home

5.0G    /home/

du和df都不太可能出错,文件系统也没有损坏的迹象,那问题出在哪儿呢?查看unlink系统调用的手册页:
Read the rest of this entry »

Oct
27

Bash quote trap: why rsync exclude pattern not work

A friend wanted to sync all his files to a remote host, exluding the source files(those with suffix .c, .cpp, .h, .hpp). First I wrote this script

#!/bin/bash
####sync.sh (version 1): sync files to remote host###
SYNC_DST='xxx@example.com::sample_project'
SYNC_OPT=' --exclude="*.[ch]" --exclude="*.[ch]pp" '
if [[ $# -eq 0 ]]; then
        echo "Usage $0 /src/path"
        exit 1
fi
src=$1
#for debug ...
echo rsync -avz $SYNC_OPT "$src" "$SYNC_DST"
rsync -avz $SYNC_OPT "$src" "$SYNC_DST"

Now we try to sync the ‘src’ directory:

./sync.sh src
####output########################################
rsync -avz --exclude="*.[ch]" --exclude="*.[ch]pp" src xxx@example.com::sample_project
sending incremental file list
src/
src/main
src/main.c
src/main.o
src/lib/
src/lib/lib.c
src/lib/lib.h
src/lib/lib.o
####output########################################
 Read the rest of this entry »

Oct
02

Using libcurl: follow redirect and get header only

Let’s look at a sample code first(I use the WWW::Curl perl module here, the idea is the same for other language).

#!/usr/bin/perl
use warnings;
use strict;

use WWW::Curl::Easy;

my $url = 'http://search.cpan.org/CPAN/authors/id/L/LO/LORN/LWP-Curl-0.09.tar.gz';
my $resp_body;

#Get file length via HTTP HEAD  request
my $length;
my $curl = WWW::Curl::Easy->new();
$curl->setopt(CURLOPT_URL, $url);
#follow redirect
$curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
#inlcude header in response
$curl->setopt(CURLOPT_HEADER, 1);
#do not include body in response
$curl->setopt(CURLOPT_NOBODY, 1);
$curl->setopt(CURLOPT_WRITEDATA,\$resp_body);
my $retcode = $curl->perform();
if($retcode == 0){
        print "header:$resp_body\n";
        print "*" x 80,"\n";
        $length = $curl->getinfo(CURLINFO_CONTENT_LENGTH_DOWNLOAD);
        if($length == -1 ){
                print "content length not available\n";
        }
        else {
                print "length: $length\n";
        }
}else{
        print "error happened:$retcode " . $curl->strerror($retcode) ." | "
                . $curl->errbuf ."\n";
        exit 1;
}

There’s nothing complicated, the points are:

  • CURLOPT_FOLLOWLOCATION: set to 1 to follow HTTP redirect response
  • CURLOPT_HEADER: set to 1 to include HTTP Header in response
  • CURLOPT_NOBODY: set to 1 to exclude body content from response, so that we get header only
  • CURLOPT_WRITEDATA: you get HTTP headers here, more about this later

You may think that we should use CURLOPT_WRITEHEADER to collect the HTTP headers, but it doesn’t work,we get only the first response header in this way, not the final headers after several redirection.

check http://curl.haxx.se/libcurl/ for more about libcurl

Aug
19

add utf8 subject support to mailwatch 1.0.5

In mailwatch v1.0.5, if the subject of a message is utf8 encoded, it can’t display correctly on the message list page. All the non-ascii characters will be replaced with question mark. For example. the subject “我爱Linux” will appears as “??Linux”.

We can patch mailwatch to support this:

1. patch Mailwatch.pm

--- MailWatch.pm.bak    2011-08-19 14:15:45.565769650 +0800
+++ MailWatch.pm        2011-08-19 15:08:47.343311859 +0800
@@ -284,7 +284,7 @@
    $msg{from_domain} = $message->{fromdomain};
    $msg{to} = join(",", @{$message->{to}});
    $msg{to_domain} = $todomain;
-   $msg{subject} = $message->{subject};
+   $msg{subject} = $message->{utf8subject};
    $msg{clientip} = $clientip;
    $msg{archiveplaces} = join(",", @{$message->{archiveplaces}});
    $msg{isspam} = $message->{isspam};

2. patch mailscanner/detail.php

--- detail.php.bak      2011-08-19 14:54:51.515734927 +0800
+++ detail.php  2011-08-19 15:04:17.003311710 +0800
@@ -147,7 +147,7 @@
    $output .= "


\n";
    $row[$f] = $output;
   }
-  if ($fieldn == "To:" || $fieldn == "Subject:") {
+  if ($fieldn == "To:") {
    $row[$f] = htmlentities($row[$f]);
   }
   if ($fieldn == "To:") {
@@ -155,7 +155,7 @@
   }
   if ($fieldn == "Subject:") {
    $row[$f] = decode_header($row[$f]);
-   //$row[$f] = htmlentities($row[$f]);
+   $row[$f] = htmlentities($row[$f],ENT_COMPAT,'utf-8');
   }
   if ($fieldn == "Spam Report:") {
    $row[$f] = format_spam_report($row[$f]);

Aug
02

Apache options directive trap

When configuring the Apache HTTP server, we use the Options directive to control which server features are available in a particular directory. We may, for example, write a config like this:

<Directory /usr/share/nagios>
    Options +ExecCGI Indexes FollowSymLinks
    ...
</Directory>

With this configuration, we hope to enable CGI if it has not been enabled, and set auto index and follow symlink option. However, this is completely wrong and will not work. when you access a cgi in this directory, you will get a 403 Forbidden page.
Read the rest of this entry »

Jul
29

Build the Linux kernel for other host

Building the linux kernel is time and resource consuming, especially when you do this in a VM guest.

fortunately, We can choose a fast Linux machine to take the burden of building, then install the kernel to the target Linux host

This simple article assumes that you know how to config and compile your custom kernel. so I will focus on building the kernel for other host.

1. Download the linux kernel from kernel.org. extract, make xxxconfig, then make, assume that the directory you build your kernel is called KERNEL_BUILD_DIR
Read the rest of this entry »

Jul
20

Install from source or use rpm, this is a question

For RHEL and its derived distribution, installing software packages using rpm or yum is sometimes convenient, painless and time saving. However, because distribution vendors build rpms independent of software provider, there may be time delay, and even inconsistency between rpms and the original software package.

Here’s what I come across today. I installed ProFTPD from the epel repo on two servers. One is CentOS 6.0 and the other is CentOS 5.6.

#on CentOS 6.0
[curu@el6 ~]$ rpm -q proftpd
proftpd-1.3.3e-1.el6.x86_64
#on CentOS 5.6
[curu@el5 ~]# rpm -q proftpd
proftpd-1.3.3e-1.el5

Seems they are of the same version. However, When I copy the proftpd.conf from el6 to el5, I get this error

proftpd -t
Checking syntax of configuration file
 - Fatal: VRootAlias: source path 'etc/security/pam_env.conf' is not an absolute path on line 11 of '/etc/proftpd.conf'

And here’s line 11 of my /etc/proftpd.conf

VRootAlias                      /etc/security/pam_env.conf etc/security/pam_env.conf

According to the mod_vroot document on proftpd site

VRootAlias
Syntax: VRootAlias src-path dst-path

It’s obvious that my config is right, the src-path here is /etc/security/pam_env.conf, definitely absolute! But what’s wrong? Ask the source!

In order to find the cause of this inconsistency, I downloaded the source rpms of these two rpms, and finally find why. In fact, in the RPMs from EPEL, proftpd-1.3.3e-1.el5 comes with mod-vroot-0.8.5, whereas proftpd-1.3.3e-1.el6 comes with mod-vroot-0.9.2. The bad thing is, the directive syntax of VRootAlias has changed between these two version of mod_vroot.

for mod-vroot-0.8.5

VRootAlias
Syntax: VRootAlias dst-path src-path

Damn! the change is completely nonsense and incompatible.

So, what can when draw from this story? Install software packages from prebuilt rpm is not always simple and good. If we need more configure option and consistent behavior, build from source.

Jul
08

Shorewall: allow communication between VPN clients

If you setup Linux as a PPTP or L2TP/IPSec VPN server, every client connection will have a corresponding pppx interface on the server. You may have a shorewall interface config like this:

/etc/shorewall/interfaces

#zone interface boradcast options
l2tp    ppp+    -

Assume that client A connected, get IP 192.168.1.100 for ppp0, client B get IP 192.168.1.101 for ppp1. When client A try to ping client B. you may get the following shorewall log:

Jul  8 00:19:20 vpngateway kernel: Shorewall:FORWARD:REJECT:IN=ppp0 OUT=ppp1
 SRC=192.168.1.100 DST=192.168.1.101 LEN=60 TOS=0x00 PREC=0x00 TTL=127 ID=311
 PROTO=ICMP TYPE=8 CODE=0 ID=1 SEQ=52

In this case, if you really think that the connected VPN clients should be able to communicate with each other, you may add the routeback option to shorewall-interface config file, like this:

#zone interface boradcast options
l2tp    ppp+    -       routeback

Reference: shorewall-interfaces man page

Jul
02

Fedora 15 下安装 Openfetion 2.2

本文简要描述在Fedora 15系统下编译安装Openfetion 2.2的办法

在Linux下编译安装软件,做多了就会知道,常见问题无非就是缺少依赖的库(头文件或者共享库)。下面给出的命令假设你以普通用户登录系统,并且这个用户具有sudo成root的权限。

1. 安装所需软件开发包


sudo yum install cmake libnotify-devel gstreamer-devel \
	NetworkManager-develgtk2-devel openssl-devel libXScrnSaver-devel

Read the rest of this entry »

Jun
17

Create new KVM guest from template

Most of us don’t like to install guest OS repeatedly, instead, we often install one guest OS, then do some setup and customization. After that, we make a backup of the disk image(We use it as a template). If we want to install the same OS later, we only need to copy that template disk image and create a new guest config file.

When create a new guest config file, we need to give it a unique name, a unique uuid, and a unique MAC address. Also, we need to change it’s disk file path. We can do this kind of changes manually, hower, according to the rule “automate all that can be automated”, we can use a script to do this.
Read the rest of this entry »

Older posts «