存档

2015年9月 的存档

在linux上用dd命令实现ghost功能

2015年9月19日 评论已被关闭

来源于网络:伯乐在线

ghost和g4l

安装操作系统,速度太慢,整个过程太冗长乏味了。

安装过程中,需要回答若干问题,系统需要安装无数个软件,创建和写入无数的文件。因为涉及到大量的文件定位和读写,速度一定是快不起来的。

Windows下我们常常使用ghost系统来备份和刻录操作系统。ghost可以clone整个系统的镜像,然后在新的电脑上恢复,相当简单。用ghost系统安装操作系统比使用安装光盘安装系统要快捷多了,也不需要回答任何问题了。

那么,我们能不能用ghost来备份和恢复Linux系统呢。

答案是不行。因为ghost只能识别很少的老旧Linux文件系统,也无法识别grub和LILO等引导加载程序。

其实,Linux下也有ghost工具,最著名的有g4l—ghostForLinux。

用了一下ghostForLinux。如果是整个磁盘的复制和恢复,还算简单。但是,我试了半天,也没办法实现对一个或者几个分区的恢复。

g4l,还是太弱了,无法满足我的要求!

神奇的fdisk和dd命令

深深的苦恼中,灵光乍现:神奇的ghost的原理是什么呢?不就是数据复制吗?Linux下的dd命令不就是最强大的数据复制工具!

既然如此,我为什么要使用g4l这样复杂的工具呢?一条dd命令不就可以帮我实现任意复杂的镜像复制和恢复的需求了吗?管他是grub,还是ext4,btrfs,FAT32,NTFS…dd面前众生平等。

进入Linux操作系统,打开命令行,执行如下命令:

1
sudo  fdisk -u -l

可以查看所有磁盘上的所有分区的尺寸和布局情况。

-u,让start和end中数字的单位是512字节,也就是一个sector扇区的大小。

假设我有一个/dev/sda磁盘,有100GB大小。我安装了一个Ubuntu操作系统。使用了如下分区:

/dev/sda1 5GB

/dev/sda2 1GB扩展分区

/dev/sda5 1GB扩展分区

/dev/sda2是所有扩展分区,它的大小和/dev/sda5重合。

/dev/sda1是ext4格式的文件系统。用于安装ubuntu操作系统。

/dev/sda5是swap格式的文件系统,作为交换分区。

如果我用弱智的g4l工具制作系统的镜像,就需要备份整个磁盘100GB,而不是我需要的6GB。

g4l也可以单独备份分区,但是在恢复时,就需要在目标计算机上安装好grub,并进行了适当的分区。很麻烦!

我这里,可以使用一条dd命令就生成6GB的镜像。然后可以在任意硬盘大于6GB的计算机上恢复出完整的系统,包括MBR和3个分区sda1,sda2,sda5。

具体步骤

找一个U盘,安装UbuntuLive Cd系统。【具体如何制作U盘启动的UbuntuLive CD,可以参考Ubuntu官方网站的帮助。】

UbuntuLive Cd和WindowsPE系统类似,是光盘/U盘引导的Ubuntu操作系统,不需要安装就可以直接使用。

U盘启动,进入盘上的Ubuntu系统,打开命令行,执行:

1
sudo  fdisk -u -l /dev/sda

查看硬件的分区情况。

然后执行:

1
dd   bs=512 count=[fdisk命令中最大的end数+1] if=/dev/sda of=/ghost.img

这样,就可以把我需要的分区数据全部copy到ghost.img文件中。镜像制作完成了!

然后,我们就可以把U盘插到其他系统上,用U盘启动,进入UbuntuLiveCD,打开命令行,执行如下命令:

1
dd if=/ghost.img of=/dev/sda

完成后,拔掉U盘,启动计算机,就可以看到我们的Linux系统已经安装完毕了!

注意:

不要直接在计算机上用本地磁盘启动系统后执行dd命令生成本地磁盘的镜像。而应该使用livecd启动计算机。

因此计算机运行时会对系统盘产生大量写操作。 直接对运行中的系统盘生成的镜像,在恢复到其他硬盘上时,很可能会无法启动!

一样适用于非Linux操作系统

在linux上用dd命令实现系统镜像备份和恢复,是不是很简单呢?

对于Windows系统,甚至Mac等等任意系统,其实都可以用dd命令实现系统镜像的备份和恢复。

因为,Linux的fdisk命令能够识别任意系统下的分区格式。fdisk并不关系分区上的文件系统,甚至有无文件系统都不关心。fdisk总是可以报告分区占用了哪些扇区。

dd命令也不关心磁盘的文件系统格式,它只是简单地按照要求从指定的位置,复制多少字节数据而已。

dd命令实现镜像备份和恢复,比Ghost软件简单和强大多了。使用ghost软件,依然需要用户进行复杂而危险的磁盘分区操作。

而使用fdisk和dd这两条命令,一切都免了!

压缩和解压缩

可能我们需要备份的分区很大,使用dd命令生成的镜像文件也就很大。存储和传输这些镜像不太方便。  我们也可以使用压缩程序压缩生成的镜像文件。 这里,我选择使用gzip程序,配合dd命令一起使用。

gzip参数:

-c 表示输出到stdout
-d  表示解压缩
-1 表示最快压缩
-9 表示最好压缩
默认使用的是-6压缩级别。

要使用 dd 和 gzip 生成压缩的镜像文件,可以执行命令:

1
dd   bs=512 count=[fdisk命令中最大的end数+1] if=/dev/sda | gzip -6 > /ghost.img.gz

还原时,可以执行下列命令:

1
gzip -dc /ghost.img.gz.gz | dd of=/dev/sda

提醒:

如果你把镜像恢复到另一台计算机上,你可能会发现你的网卡是eth1,而不是eth0。这是因为/etc/udev/rules.d/70-persistent-net.rules文件把你做镜像的计算机的网卡作为eth0登记了。

如果你的网络脚本对eth0进行了处理,而没有对eth1进行处理,那么不修改网络脚本,你可能就无法上网了。

也许你会希望在做镜像之前,先删除 /etc/udev/rules.d/70-persistent-net.rules 文件。这样你恢复镜像时,网卡的名字就是eth0。   就不会造成你在恢复后的计算机上无法上网的问题了。

注意:

最好在dd生成镜像之前,先umount所有 if和of 设备的分区。这样可以确保在dd的过程中文件系统没有被改变。

在完成dd(生成镜像和恢复镜像)后,执行sudo sync,确保数据被真正写入到硬盘上。

另外,如果你想要对整个硬盘进行备份和恢复,而不是只备份和恢复部分分区,那么就请把dd命令中的 count=[fdisk命令中最大的end数+1]   去掉。bs=512也可以去掉。

分类: Linux 标签:

最简单实现跨域的方法:使用nginx反向代理

2015年9月19日 评论已被关闭

来源于网络:伯乐在线

什么是跨域

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。

所谓同源是指,域名,协议,端口相同。浏览器执行javascript脚本时,会检查这个脚本属于那个页面,如果不是同源页面,就不会被执行。

同源策略的目的,是防止黑客做一些做奸犯科的勾当。比如说,如果一个银行的一个应用允许用户上传网页,如果没有同源策略,黑客可以编写一个登陆表单提交到自己的服务器上,得到一个看上去相当高大上的页面。黑客把这个页面通过邮件等发给用户,用户误认为这是某银行的主网页进行登陆,就会泄露自己的用户数据。而因为浏览器的同源策略,黑客无法收到表单数据。

现在随着RESTFUL的流行,很多应用提供http/https接口的API,通过xml/json格式对外提供服务,实现开放架构。如,微博、微信、天气预报、openstack等网站和应用都提供restful接口。

Web应用也在向单页面方向发展。

越来越多的web应用现在是这样的架构:

静态单个web页面

ajax调用

RESTFUL服务

我们本可以利用各个网站提供的API,做出很多精彩的Web应用。但浏览器执行javascript时的跨域限制,就成为了这类开放架构的拦路虎。

本文提出了一种简单有效的方式解决跨域问题。

常用的跨域方法

常用的跨域方法有这样一些:

1,使用iFrame访问另一个域。 然后再从另一个页面读取iFrame的内容。jquery等有一些封装。

据说Firefox等可能不支持读取另一个iFrame的内容。

2,jsonp。需要服务器支持。使用script src动态得到一段java代码。是回调页面上的js函数,参数是一个json对象。

jquery也有封装。

3,设置http头,Access-Control-Allow-Origin:*

但据说IE有一些版本不识别这个http头。

4,服务器代理。如,服务器写一个url的处理action。其参数是一个url。这个服务器会用参数拼凑一个url,用httpclient库去执行url,然后把读取的内容再输出到http客户端。

nginx反向代理实现跨域

上面提到的这些跨域方法,都有一些问题。有的不能支持所有浏览器,有的需要修改javascript代码,有的需要重写服务器端代码。有的在session等场景下会有问题。

其实,用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。

我们只需要配置nginx,在一个服务器上配置多个前缀来转发http/https请求到多个真实的服务器即可。这样,这个服务器上所有url都是相同的域名、协议和端口。因此,对于浏览器来说,这些url都是同源的,没有跨域限制。而实际上,这些url实际上由物理服务器提供服务。这些服务器内的javascript可以跨域调用所有这些服务器上的url。

下面,给出一个nginx支持跨域的例子,进行具体说明。

如,我们有两个pythonflask开发的项目:testFlask1和testFlask2。

testFlask2项目上的javascript脚本要通过ajax方式调用testFlask1的一个url,获取一些数据。

正常情况下部署,就会有跨域问题,浏览器拒绝执行如下这样的调用。

1
2
3
4
5
$("button").click(function () {
    $.get("127.0.0.1:8081/partners/json", function (result) {
        $("div").html(result);
    });
});

下面把testFlask2项目的javascrip文件修改一下。这样访问同源的url,就不会有跨域问题。

1
2
3
4
5
$("button").click(function () {
    $.get("partners/json", function (result) {
        $("div").html(result);
    });
});

但是,我们testFlask2项目实际上没有partners/json这样的url,那怎么处理呢?

我们这样编写nginx的配置文件:

 

1
2
3
4
5
6
7
8
9
10
11
12
server{
  listen8000;
  location/ {
    includeuwsgi_params;
    uwsgi_passunix:/tmp/testFlask2.sock;
  }
  location/partners {
    rewrite^.+partners/?(.*)$ /$1 break;
    includeuwsgi_params;
    uwsgi_passunix:/tmp/testFlask1.sock;
  }
}

我们把testFlask2项目部署在8080端口的根目录下。把提供web服务的testFlask1项目部署在/partners目录下。

但我们的testFlask1项目并不能处理/partners/json这样的url请求。那怎么办呢?

通过rewrite^.+partners/?(.*)$ /$1 break; 这一条命令,nginx可以把收到的/partners/*请求全部转为/*请求后再转发给背后的真实web服务器。

这样,RESTFUL的ajax客户端程序,只需要给出特定前缀的url就可以调用任意服务器提供的RESTFUL接口了。

甚至,通过nginx的反向代理,我们还能调用其他公司开发的网站提供的RESTFUL接口。

如,

1
2
3
4
5
location/sohu {
  rewrite^.+sohu/?(.*)$ /$1 break;
  includeuwsgi_params;
  proxy_passhttp://www.sohu.com/;
}

我们就把sohu网站整个搬到我们的8080:/sohu/目录下了,我们的javascript就可以尽情调用其RESTFUL服务了。

顺便说一下,rewrite^.+sohu/?(.*)$ /$1 break;  这句命令中,$1表示(.*)这个部分。第一对()内的参数是$1,第二对()内的参数就是$2,以此类推。

总结

本文介绍了利用nginx的反向代理的功能,实现跨域访问任意应用和网站的方法。

nginx是一个高性能的web服务器,常用作反向代理服务器。nginx作为反向代理服务器,就是把http请求转发到另一个或者一些服务器上。

通过把本地一个url前缀映射到要跨域访问的web服务器上,就可以实现跨域访问。

对于浏览器来说,访问的就是同源服务器上的一个url。而nginx通过检测url前缀,把http请求转发到后面真实的物理服务器。并通过rewrite命令把前缀再去掉。这样真实的服务器就可以正确处理请求,并且并不知道这个请求是来自代理服务器的。

简单说,nginx服务器欺骗了浏览器,让它认为这是同源调用,从而解决了浏览器的跨域问题。又通过重写url,欺骗了真实的服务器,让它以为这个http请求是直接来自与用户浏览器的。

这样,为了解决跨域问题,只需要动一下nginx配置文件即可。简单、强大、高效!

分类: javascript, nginx 标签:

linux 定期自动备份mysql的shell

2015年9月17日 评论已被关闭

来源于网络:http://blogread.cn/it/article/6089?f=wb

– – –

#!/bin/sh

# mysql_backup.sh: backup mysql databases and keep newest 5 days backup.

#

# db_user is mysql username

# db_passwd is mysql password

# db_host is mysql host

# —————————–

db_user=”root”

db_passwd=”zhoz.com”

db_host=”localhost”

# the directory for story your backup file.

backup_dir=”/home/zhozdbbackup”

# date format for backup file (dd-mm-yyyy)

time=”$(date +”%d-%m-%Y”)”

# mysql, mysqldump and some other bin’s path

MYSQL=”/usr/bin/mysql”

MYSQLDUMP=”/usr/bin/mysqldump”

MKDIR=”/bin/mkdir”

RM=”/bin/rm”

MV=”/bin/mv”

GZIP=”/bin/gzip”

# check the directory for store backup is writeable

test ! -w $backup_dir && echo “Error: $backup_dir is un-writeable.” && exit 0

# the directory for story the newest backup

test ! -d “$backup_dir/backup.0/” && $MKDIR “$backup_dir/backup.0/”

# get all databases

all_db=”$($MYSQL -u $db_user -h $db_host -p$db_passwd -Bse ‘show databases’)”

for db in $all_db

do

$MYSQLDUMP -u $db_user -h $db_host -p$db_passwd $db | $GZIP -9 > “$backup_dir/backup.0/$time.$db.gz”

done

# delete the oldest backup

test -d “$backup_dir/backup.5/” && $RM -rf “$backup_dir/backup.5”

# rotate backup directory

for int in 4 3 2 1 0

do

if(test -d “$backup_dir”/backup.”$int”)

then

next_int=`expr $int + 1`

$MV “$backup_dir”/backup.”$int” “$backup_dir”/backup.”$next_int”

fi

done

exit 0;

 

分类: db, Linux 标签:

管理Gearman

2015年9月9日 评论已被关闭

通常,Gearman被用来分发任务,以便实现非堵塞。下面捋捋如何管理Gearman。

说明:请自行安装好Gearman和PHP PECL Gearman。

准备

我们先来创建一个Worker,实现一个简单的显示功能:

[pcsh lang=”php” tab_size=”4″ message=”” hl_lines=”” provider=”manual”]

$worker= new GearmanWorker();

$worker->addServer('127.0.0.1', '4730');

$worker->addFunction('echo', 'my_echo_function');

while ($worker->work());

function my_echo_function($job) {
    return $job->workload();
}

[/pcsh]

然后我们运行它:

shell> php /path/to/worker/file

 

可能你已经注意到,代码里有一个死循环,是不是需要Sleep一下?让我们监测看看:

shell> strace -r php /path/to/worker/file
0.000099 poll([{fd=3, events=POLLIN}], 1, 10000) = 0 (Timeout)
10.006522 write(3, "\0REQ\0\0\0\t\0\0\0\0", 12) = 12

 

可见PHP PECL Gearman内部已经做了休息十秒的设置,我们就不用杞人忧天了。

接下来我们以Shell为Client来调用一下:

shell> gearman -f echo "hello, world."

 

到这里,准备工作基本就齐活儿了,相信大家已经对Gearman有了一个初步的认识。

管理

出于效率的考虑,我们往往会启动很多个Worker,但具体应该启动多少个呢?十个还是一百个?少了不够,多了浪费,到底应该如何度量呢?

其实Gearman本身已经提供了相应的命令供我们查看状态:

shell> (echo status; sleep 0.1) | nc 127.0.0.1 4730

 

命令的结果会分为四列,它们的含义从左到右依次是:

  1. Function name: A string denoting the name of the function of the job
  2. Number in queue: A positive integer indicating the total number of jobs for this function in the queue. This includes currently running ones as well (next column)
  3. Number of jobs running: A positive integer showing how many jobs of this function are currently running
  4. Number of capable workers: A positive integer denoting the maximum possible count of workers that could be doing this job. Though they may not all be working on it due to other tasks holding them busy.

 

从这些信息可以推断出:如果系统比较繁忙的话,Number of jobs running的数值会接近Number of capable workers;Number in queue可能会大于Number of capable workers。此时我们应该增加Worker的数量,反之则应该考虑减少Worker的数量。

另外,推荐大家结合使用watch命令来监控Gearman的状态,这样更直观一些:

shell> watch -n 1 "(echo status; sleep 0.1) | nc 127.0.0.1 4730"

 

实际应用中,还有很多特殊情况需要考虑,比如说:程序代码更新后,如何避免手动重启Worker?还需要注意的是Worker长时间运行,一旦意外中断或者内存泄漏怎么办?通常这类进程控制问题用Supervisor都可以轻松搞定,有兴趣的读者自己看看吧。此外网络上还有一些不错的工具可以玩玩,比如:GearmanManagerGearman-Monitor

来源:火丁笔记

 

分类: Linux, PHP 标签: