vagrant 配置windows虚拟机

相比较在vagrant中配置centos来讲,配置windows会比较麻烦而且特殊一些,下面记录一些自己的经历。

第一步:创建虚拟机

由于windows的vbox不多,能找到一个适合自己的也不太容易,倒不如自己在virtualbox中直接用iso文件安装一个,安装完成后直接: vagrant package –base the_virtualbox_vm_name –output my_windows.box

由于windows不比centos可以使用ssh登录,而是有自己的管理方式,叫做wrm,这个必须在安装windows的时候都设置好,参考资料:

下面是我遇到过的一些问题:

  1. 为了避免忘记密码,干脆没给用户设置密码;然而,wrm要求管理员用户必须设置密码,否则,无法配置wrm;就因为这个浪费了不少时间
  2. 网络连接类型不能是公共网络,否则wrm不允许使用
  3. 为了不必要的麻烦,干脆把防火墙给关掉了

重要配置:

曾经因为没有设置@{AllowUnencrypted=”true” }  和 @{Basic=”true”} 浪费了很多时间

关闭UAC: http://jingyan.baidu.com/article/09ea3ede241689c0afde3972.html

第二步: 配置vagrantfile

vagrant默认使用ssh,而windows要使用wrm,那么,总得有个方式说明一下吧?vagrant官网文档查看了一大片,没找到,最后还是在 http://huestones.co.uk/node/305  找到的,如下:

windows中很可能会出现未识别的网络或者是“公用网络”,在这种情况下,winrm是不能正常使用的,所以,保险起见,vagrantfile中添加如下设置:

确保不会出现公用网络,曾经因为这个浪费了不少时间

 

附:一个windows的vagrantfile

 

附:

如何给设置的ip指定掩码(默认24位)? 如下指定22位掩码:

windows的“未识别网络”是什么意思?

当本地连接设置为“自动获取IP地址”,同时网络中又没有dhcp服务器,则该本地连接会被标识为“未识别网络”;如果在所在网络提供一个dhcp服务器,就会避免此种问题的出现

 

 

Docker存储扩容

 

脚本:

参考:

https://docs.docker.com/engine/userguide/storagedriver/device-mapper-driver/

http://jpetazzo.github.io/2014/01/29/docker-device-mapper-resize/  翻译版: https://segmentfault.com/a/1190000002931564

https://segmentfault.com/a/1190000004302467  这里的扩容方式比较低级,是丢失数据的扩容方式

https://docs.docker.com/engine/userguide/

https://developerblog.redhat.com/2014/09/30/overview-storage-scalability-docker/

http://blog.opskumu.com/docker-storage-setup.html

http://coolshell.cn/articles/17200.html   这篇文章非常不错

关于最近我的blog经常没有响应的问题

最近,经常出现我的blog不能响应的问题,起初怀疑网络问题,因为我是部署在阿里云的。后来,忍无可忍,查了一下:

  1. 首先,浏览器中不能响应的时候,curl还是能正常访问的
  2. 其次,通过tcpdump抓包发现,确实是请求发送到了server,而server没有回应
  3. strace跟踪server端进程,发现大量进程在试图flock 一个文件,lsof查看,发现确实在试图lock我的session文件
  4. 肯定有一个进程lock住session文件后,在干别的耗时的事情,一直也没干完
  5. 继续strace打开session文件的每一个进程,必然会有一个文件打开了session文件,但是没有处于flock系统调用阶段,果然,是进程15822
  6. pstack 15822, 结果如下:

     
  7. 显然,该进程正在试图通过curl访问一个外部资源,应该是连接不上,lsof 查看部分结果如下:
  8. 一切不出所料,但是,至此,我根据上面信息还无法知道究竟是哪个逻辑要访问该资源
  9.  借助php源码中提供的 .gdbinit 通过zbacktrace来看,不过忙了一会儿,进程不在了,下次再说吧
  10. N 天后,相同问题再次出现,本次进程id: 826
  11. 直接 gdb -p 816 然后zbacktrace
    最后发现由于插件: /data1/www/htdocs/phpor.net/blog/wp-content/plugins/google-analytics-dashboard/ga-lib.php 导致,相关域名: www.googleapis.com ; 域名解析发现果然和上述IP契合
  12. 解决办法,直接禁用该插件

cobbler 配置镜像源

对于一个公司来讲,为了安装软件方便,最好有一个自己的yum源镜像,下面介绍用cobbler配置镜像源。

  1. 下载安装cobbler 《略》
  2. 配置cobbler 《略》
  3. 添加镜像源,如:
  4. 编辑已添加的镜像源
    把 add 换作 edit,其余的需要修改哪项就该对应参数即可
  5. 删除镜像源 《略》

注:

  1. cobbler只同步每个rpm的最新版本,就的版本就不见了《如何保留旧版本呢?》
  2. 每个镜像源对应一个目录,该目录下会有repodata子目录,如果没有这个目录就不是一个有效的yum源
  3. 每个镜像源目录下有一个config.repo 文件,用于写在 /etc/yum.repos.d/ 下面的,只是需要修改一下里面的地址
  4. 对于多个镜像源使用多个文件的话,使用起来也不方面,下面有一个脚本可以将多个config.repo 合并为一个

    注意: 或许你会去每个目录下find config.repo ,因为rpm包非常多,find的效率会非常低,而使用 */config.repo 将是瞬间完成的

Docker 都依赖哪些东西

下面是docker安装的一个过程:

 

Centos6上单个多个进程listen同一个端口的问题

原来有文章提到过,Centos7上多个进程可以同时listen同一个端口,起到负载均衡的效果,也方便实现服务的无缝升级; 但是Centos6上多个进程同时listen同一个端口的情况怎么理解呢?

首先,这事儿并不新鲜,正常情况下php-fpm的每个子进程都在listen中父进程集成下来的9000端口的,这个并不冲突;但是下图有显示ssh和fpm同时listen 9000端口:

何故?会有问题吗?

进程说明: web server通过fpm提供了一个命令执行的功能,通过shell_exec()执行的,命令执行的是一个ssh命令,执行时间比较长;该ssh进程继承了父进程的文件描述符 *:9000 就被listen了,显然,该ssh进程其实是不会去accept该 *:9000 端口的,所以正常请求不会被ssh意外处理的。

似乎没啥问题,但是确实有问题:

fpm master派生新的子进程后,新的子进程不能正常accept该文件描述符,strace跟踪部分输出如下:

我们发现,fpm子进程accept(0,…) 报“资源临时不可用”,然后直接退出,然后fpm-master继续派生新的子进程,然后再退出,迅速重复该过程,结果:

  1. 机器负载飙升
  2. fpm-master几乎无法立即给每个退出的子进程收尸,于是出现大量fpm子进程处于 僵尸状态

问题:

  1. web shell曾经也做过,为啥没见过这个问题?
  2. 为啥会出现这种情况?

 

附:

服务器版本信息:

C语言中的可变参数

参考: http://www.tutorialspoint.com/c_standard_library/c_macro_va_start.htm  (这的代码可以执行的哦)

 

指南站: http://www.tutorialspoint.com

shell 基础

echo $str    与  echo  “$str” 的不同:

cmd $a  与 cmd “$a” 的不同:

如果$a=”a b”; 即:包含空格

前者: cmd接到的是2个参数

后者: cmd接到的是1个参数

举个栗子:如下图,我要把grep的那个关键字用变量替换:

  1. 直接 grep $keywords 测试是不行的,相当于grep 接收了两个参数
  2. 于是乎考虑拼凑第一条命令,就是把单引号拼上:
    grep ‘$kerwords’ 显然是不行的,因为单引号里面的变量是不被替换的
    grep “‘$keywords'” 似乎很完美了,不仅能替换变量,还能添加单引号;上图来看,结果没符合预期,且看下面测试:

    显然,这里的单引号参数值的一部分,而上图第一行的单引号仅仅是在形式化一个参数,是在解释阶段被处理的,至于是单引号还是双引号都关系不大;本质上,我们要保证的是替换后的变量要作为一个(而不是多个)参数传递给grep;从上面我们分析的 $a 和 “$a”的区别,我们便可以知道,其实直接grep “$keyword”就可以了
  3. 总结: 很多情况下,我们是要注意$var 最好写成 “$var” 的;我们经常想要的是 “$var” ,而不是 $var

cmd $a $b 与 cmd “$a” “$b”

前者如果$a为空,则 $1得到的将是$b的值,出现参数错位的情况;后者则不会出现这种情况

管道到read

a b 变量没有被成功赋值;
原因: 由于管道的存在,默认情况下,第一个管道的前面部分是在当前bash进程中执行的,后面的被管道隔开的命令都是在单独的子shell中执行的,那么是bash的内置命令(如:read)也要单启动一个bash进程来执行,而子进程中的变量不会对父进程产生影响,显然,例子中read a b里面的a b是子进程中的变量,在父进程中是不能echo出来的。

据说bash提供了一个选项lastpipe,可以改变bash的行为,使得管道链中的最后一个命令在当前bash中执行,其他的命令都在子shell中执行,不过我的bash目前是4.1(目前最新是4.4,还没stable),还没有这个选项,通过shopt查询是否有该选项。不过,据说使用该选项将不得不禁用作业控制。

还有其他办法:

办法1: 使用Here Document

办法二: 使用Here String

办法三: 使用Here Command

这个似乎应该叫做Process Substitution

参考: http://www.tldp.org/LDP/abs/html/process-sub.html

参考资料: http://stackoverflow.com/questions/13763942/bash-why-piping-input-to-read-only-works-when-fed-into-while-read-const

搜索: https://www.google.com.hk/?gws_rd=cr,ssl#safe=strict&q=bash+read+pipe+into+variable

关于here document、here string

here文档和here字符串不同于其他语言中仅仅用来定义复杂的字符串的,而是有特殊目的的,bash中的here文档和here字符串是用在命令后面的,他自动修改了命令的标准输入,如:

错误用法:

我们发现 变量a没有被成功复制。

hello world也没有成功被打印出来。

正确的用法:

等效于:

《Advanced Bash-Scripting Guide》中是这么说的:

A here document is a special-purpose code block. It uses a form of I/O redirection to feed a command list to an interactive program or a command, such as ftp, cat, or the ex text editor.

 

参考资料: http://www.tldp.org/LDP/abs/html/here-docs.html

关于 Here command

没有找见这方面的文档

关于字面量

对于 echo “$a”  大可不必担心 $a 有函数 双引号而在替换后破坏结构;如果a='”123′ , 则不必担心echo “$a” 会被处理成 echo “”123”

关于花括号扩展

花括号与元素之间不能有空格,元素之间逗号分隔且不能有空格

如果花括号中的元素含有变量,而变量中含有空格是没有问题的,但是空格元素可能会被丢掉,所以,为了不发生意外,变量最好用双引号引起来

 

$* vs $@

参考: http://c.biancheng.net/cpp/view/2739.html

https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html