sean xiao

  • 主页
  • 所有文章
所有文章 关于我

sean xiao

  • 主页
  • 所有文章

Linux下操作'>>'操作符遇到的坑

2016-01-24

今天,在写一个脚本,需求是统计出年nginx的日志文件:access.log中用户访问的IP的次数。
由于我的开发环境是在Linux下面,于是我采用Linux下面的awk命令进行统计。

文件1.access.log是有满足awk查询条件的内容,这里列2条

1
2
3
192.168.161.2 - - [17/Jan/2016:11:18:53 +0800] "GET / HTTP/1.0" 301 178 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" 0.000 - "66.249.64.187"
192.168.161.2 - - [19/Jan/2016:14:37:17 +0800] "POST /xx/captcha HTTP/1.0" 440 125 "xxx" "Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; SM705 Build/SANFRANCISCO) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025489 Mobile Safari/533.1 MicroMessenger/6.3.9.48_refecd3e.700 NetType/WIFI Language/zh_CN" 0.061 0.060 "192.168.225.61, 192.168.225.61"
192.168.161.2 - - [19/Jan/2016:14:37:17 +0800] "GET /xx HTTP/1.0" 200 4303 "xxx" "Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; SM705 Build/SANFRANCISCO) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025489 Mobile Safari/533.1 MicroMessenger/6.3.9.48_refecd3e.700 NetType/WIFI Language/zh_CN" 0.159 0.159 "192.168.225.61, 192.168.225.61"

执行代码(注意这里写文件操作的是用>>,数据添加文件后面):

1
2
3
4
5
6
7
8
9
<?php
$fileName = '/var/log/nginx/1.access.log';
$outFile = '/usr/share/nginx/www/test/async/ip.log';
//awk '{a[$1]+=1;}END{for(i in a){print i,a[i]}}' /var/log/nginx/1.access.log >> /usr/share/nginx/www/test/async/ip.log &
$command = 'awk \'{a[$1]+=1;}END{for(i in a){print i,a[i]}}\' ' . $fileName . ' >> '.$outFile.' &';
//awk这个命令的功能就是将第一行的IP地址提取出来,并且统计次数。
system($command);
var_dump(file_get_contents($outFile));
?>

执行文件输出的内容:

1
string(0) ""

现在问题出现了:当我们在Linux命令行下面执行$command里面的内容,是可以在$outFile里面查看到我们期待的数据。但是当我在Linux下面执行PHP这个脚本的时候。出现了一个奇怪的现象:文件中是有内容的,file_get_contents却没有把内容打印出来。

结论:程序异步执行了,PHP执行完Linux的命令。Linux只是返回函数执行成功的状态,然后异步去写文件了。当PHP执行file_get_contents函数时候,Linux并没有写好文件。

现在换一种方法去获取文件的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
$fileName = '/var/log/nginx/1.access.log';
$outFile = '/usr/share/nginx/www/test/async/ip.log';
//awk '{a[$1]+=1;}END{for(i in a){print i,a[i]}}' /var/log/nginx/1.access.log >> /usr/share/nginx/www/test/async/ip.log &
$command = 'awk \'{a[$1]+=1;}END{for(i in a){print i,a[i]}}\' ' . $fileName . ' >> '.$outFile.' &';
$id = pcntl_fork();
if ($id > 0) {
pcntl_wait($status);
$childExitStatus = pcntl_wexitstatus($status);
if (0 == $childExitStatus) {
var_dump(file_get_contents($outFile));
}
} else if (0 == $id) {
system($command);
exit(0);
} else {
echo 'fail to fork child process' . PHP_EOL;
}
?>

现在我先等子进程执行完数据,然后父进程在去获取文件的内容,就可以将文件的内容打印出来了。

1
2
3
string(28) "192.168.161.2 4
127.0.0.1 1
"

  • php
  • linux

扫一扫,分享到微信

微信分享二维码
go 随机数
self与static的区别
© 2017 sean xiao
Hexo Theme Yilia by Litten
  • 所有文章
  • 关于我

tag:

  • php
  • 随笔
  • apache
  • go
  • http
  • linux
  • mongo
  • nginx
  • php5-fpm
  • yii2

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

我就是我,不需要刻意的去证明…