学习知识分享-个人学习生活分享 - 小技巧
一、合理使用Shell历史命令记录功能 在Linux下可通过history命令查看用户所有的历史操作记录，同时shell命令操作记录默认保存在用户目录下的.bash_history文件中，通过这个文件可以查询shell命令的执行历史，有助于运维人员进行系统审计和问题排查，同时，在服务器遭受黑客攻击后，也可以通过这个命令或文件查询黑客登录服务器所执行的历史命令操作，但是有时候黑客在入侵服务器后为了毁灭痕迹，可能会删除.bash_history文件，这就需要合理的保护或备份.bash_history文件。下面介绍下history日志文件的安全配置方法。 默认的history命令只能查看用户历史操作记录，并不能区分每个用户操作命令的时间，这点对于排查问题十分不便，不过可以通过下面的方法（加入四行内容）让history命令自动记录所有shell命令的执行时间，编辑/etc/bashrc文件： HISTFILESIZE=4000 HISTSIZE=4000 HISTTIMEFORMAT='%F %T' export HISTTIMEFORMAT HISTFILESIZE=4000 HISTSIZE=4000 HISTTIMEFORMAT='%F %T' export HISTTIMEFORMAT 其中，HISTFILESIZE定义了在.bash_history文件中保存命令的记录总数，默认值是1000，这里设置为4000；HISTSIZE定义了history命令输出的记录总数；HISTTIMEFORMAT定义时间显示格式，这里的格式与date命令后的“+"%F %T"”是一致的；HISTTIMEFORMAT作为history的时间变量将值传递给history命令。 通过这样的设置后，执行history命令，就会显示每个历史命令的详细执行时间，例如： [root[@server](http://my.oschina.net/u/2391656) ~\]# history 247 2013-10-05 17:16:28 vi /etc/bashrc 248 2013-10-05 17:16:28 top 249 2013-10-05 17:04:18 vmstat 250 2013-10-05 17:04:24 ps -ef 251 2013-10-05 17:16:29 ls -al 252 2013-10-05 17:16:32 lsattr 253 2013-10-05 17:17:16 vi /etc/profile 254 2013-10-05 17:19:32 date +"%F %T" 255 2013-10-05 17:21:06 lsof 256 2013-10-05 17:21:21 history 为了确保服务器的安全，保留shell命令的执行历史是非常有用的一条技巧。shell虽然有历史功能，但是这个功能并非针对审计目的而设计，因此很容易被黑客篡改或是丢失。下面再介绍一种方法，可以实现详细记录登录过系统的用户、IP地址、shell命令以及详细操作时间等，并将这些信息以文件的形式保存在一个安全的地方，以供系统审计和故障排查。 将下面这段代码添加到/etc/profile文件中，即可实现上述功能。 #history USER_IP=\`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/\[()\]//g'\` HISTDIR=/usr/share/.history if \[ -z $USER_IP \] then USER_IP=\`hostname\` fi if \[ ! -d $HISTDIR \] then mkdir -p $HISTDIR chmod 777 $HISTDIR fi if \[ ! -d $HISTDIR/${LOGNAME} \] then mkdir -p $HISTDIR/${LOGNAME} chmod 300 $HISTDIR/${LOGNAME} fi export HISTSIZE=4000 DT=\`date +%Y%m%d_%H%M%S\` export HISTFILE="$HISTDIR/${LOGNAME}/${USER_IP}.history.$DT" export HISTTIMEFORMAT="\[%Y.%m.%d %H:%M:%S\]" chmod 600 $HISTDIR/${LOGNAME}/*.history* 2>/dev/null 这段代码将每个用户的shell命令执行历史以文件的形式保存在/usr/share/.history目录中，每个用户一个文件夹，并且文件夹下的每个文件以IP地址加shell命令操作时间的格式命名。下面是user01用户执行shell命令的历史记录文件，基本效果如下： [root[@server](http://my.oschina.net/u/2391656) user01\]# pwd /usr/share/.history/user01 [root[@server](http://my.oschina.net/u/2391656) user01\]# ls -al -rw------- 1 user01 wheel 56 Jul 6 17:07 192.168.12.12.history.20130706_164512 -rw------- 1 user01 wheel 43 Jul 6 17:42 192.168.12.12.history.20130706_172800 -rw------- 1 user01 wheel 22 Jul 7 12:05 192.168.12.19.history.20130707_111123 -rw------- 1 user01 wheel 22 Jul 8 13:41 192.168.12.20.history.20130708_120053 -rw------- 1 user01 wheel 22 Jul 1 15:28 192.168.12.186.history.20130701_150941 -rw------- 1 user01 wheel 22 Jul 2 19:47 192.168.12.163.history.20130702_193645 -rw------- 1 user01 wheel 22 Jul 3 12:38 192.168.12.19.history.20130703_120948 -rw------- 1 user01 wheel 22 Jul 3 19:14 192.168.12.134.history.20130703_183150 保存历史命令的文件夹目录要尽量隐蔽，避免被黑客发现后删除。 二、合理使用su、sudo命令 su命令是一个切换用户的工具，经常用于将普通用户切换到超级用户下，当然也可以从超级用户切换到普通用户。为了保证服务器的安全，几乎所有服务器都禁止了超级用户直接登录系统，而是通过普通用户登录系统，然后再通过su命令切换到超级用户下，执行一些需要超级权限的工作。通过su命令能够给系统管理带来一定的方便，但是也存在不安全的因素，例如系统有10个普通用户，每个用户都需要执行一些有超级权限的操作，就必须把超级用户的密码交给这10个普通用户，如果这10个用户都有超级权限，通过超级权限可以做任何事，那么会在一定程度上对系统的安全造成了威协。因此su命令在很多人都需要参与的系统管理中，并不是最好的选择，超级用户密码应该掌握在少数人手中，此时sudo命令就派上用场了。 sudo命令允许系统管理员分配给普通用户一些合理的“权利”，并且不需要普通用户知道超级用户密码，就能让他们执行一些只有超级用户或其他特许用户才能完成的任务，比如系统服务重启、编辑系统配置文件等，通过这种方式不但能减少超级用户登录次数和管理时间，也提高了系统安全性。因此，sudo命令相对于权限无限制性的su来说，还是比较安全的，所以sudo也被称为受限制的su，另外sudo也是需要事先进行授权认证的，所以也被称为授权认证的su。 sudo执行命令的流程是：将当前用户切换到超级用户下，或切换到指定的用户下，然后以超级用户或其指定切换到的用户身份执行命令，执行完成后，直接退回到当前用户，而这一切的完成要通过sudo的配置文件/etc/sudoers来进行授权。 例如，/etc/shadow文件普通用户是无法访问的： [user01[@unknown](http://my.oschina.net/dust587) ~\]$ more /etc/shadow /etc/shadow: Permission denied 如果要让普通用户user01可访问这个文件，可以在/etc/sudoers添加如下内容： user01 ALL = /bin/more /etc/shadow 这样，通过如下方式user01用户就可访问/etc/shadow文件： [user01[@unknown](http://my.oschina.net/dust587) ~\]$ sudo more /etc/shadow [sudo\] password for user01: 执行这个命令后，需要输入user01用户的密码，然后就可访问文件内容了。在这里sudo使用时间戳文件来完成类似“检票”的系统，当用户输入密码后就获得了一张默认存活期为5分钟的“入场券”（默认值可以在编译的时候改变）。超时以后，用户必须重新输入密码才能查看文件内容。 如果每次都需要输入密码，那么某些自动调用超级权限的程序就会出现问题，此时可以通过下面的设置，让普通用户无需输入密码即可执行具有超级权限的程序。例如，要让普通用户centreon具有/etc/init.d/nagios脚本重启的权限，可以在/etc/sudoers添加如下设置： CENTREON ALL = NOPASSWD: /etc/init.d/nagios restart 这样，普通用户centreon就可以执行nagios重启的脚本而无需输入密码了。如果要让一个普通用户user02具有超级用户的所有权限，而又不想输入超级用户的密码，只需在/etc/sudoers添加如下内容即可： user02 ALL=(ALL) NOPASSWD: ALL 这样user02用户登录系统后，就可以通过执行如下命令切换到超级用户下： [user02@unknown ~\]$ sudo su - [root@unknown ~\]# pwd root sudo设计的宗旨是：赋予用户尽可能少的权限但仍允许它们完成自己的工作，这种设计兼顾了安全性和易用性，因此，强烈推荐通过sudo来管理系统账号的安全，只允许普通用户登录系统，如果这些用户需要特殊的权限，就通过配置/etc/sudoers来完成，这也是多用户系统下账号安全管理的基本方式。 三、删减系统登录欢迎信息 系统的一些欢迎信息或版本信息，虽然能给系统管理者带来一定的方便，但是这些信息有时候可能被黑客利用，成为攻击服务器的帮凶，为了保证系统的安全，可以修改或删除某些系统文件，需要修改或删除的文件有4个，分别是/etc/issue、/etc/issue.net、/etc/redhat-release和/etc/motd。 /etc/issue和/etc/issue.net文件都记录了操作系统的名称和版本号，当用户通过本地终端或本地虚拟控制台等登录系统时，/etc/issue的文件内容就会显示，当用户通过ssh或telnet等远程登录系统时，/etc/issue.net文件内容就会在登录后显示。在默认情况下/etc/issue.net文件的内容是不会在ssh登录后显示的，要显示这个信息可以修改/etc/ssh/sshd_config文件，在此文件中添加如下内容即可： Banner /etc/issue.net 其实这些登录提示很明显泄漏了系统信息，为了安全起见，建议将此文件中的内容删除或修改。 /etc/redhat-release文件也记录了操作系统的名称和版本号，为了安全起见，可以将此文件中的内容删除。 /etc/motd文件是系统的公告信息。每次用户登录后，/etc/motd文件的内容就会显示在用户的终端。通过这个文件系统管理员可以发布一些软件或硬件的升级、系统维护等通告信息，但是此文件的最大作用就、是可以发布一些警告信息，当黑客登录系统后，会发现这些警告信息，进而产生一些震慑作用。看过国外的一个报道，黑客入侵了一个服务器，而这个服务器却给出了欢迎登录的信息，因此法院不做任何裁决。 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/94/ 创建时间 2015-11-09 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
彻底删除微软拼音输入法这个讨厌的家伙
点点点 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/24/ 创建时间 2015-09-24 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
在日常生活中，随机数实际上经常遇到，想丢骰子，抓阄，还有抽签。呵呵，非常简单就可以实现。那么在做程序设计，真的要通过自己程序设计出随机数那还真的不简单了。现在很多都是操作系统内核会提供相应的api，这些原始参数是获取一些计算机运行原始信息，如内存，电压，物理信号等等，它的值在一个时间段可以保证是唯一的了。好了，废话我就不说了。呵呵。 shell脚本程序我们有那些获得随机数方法呢？ 一、通过时间获得随机数（date) 这个也是我们经常用到的，可以说时间是唯一的，也不会重复的，从这个里面获得同一时间的唯一值。适应所有程序里面了。 例子： [chengmo@centos5 shell]$ date +%s 1287764773 #获得时间戳，当前到：1970-01-01 00:00:00 相隔的秒数 #如果用它做随机数，相同一秒的数据是一样的。在做循环处理，多线程里面基本不能满足要求了。 [chengmo@centos5 shell]$ date +%N 738710457 #获得当前时间的纳秒数据，精确到亿分之一秒。 #这个相当精确了，就算在多cpu，大量循环里面，同一秒里面，也很难出现相同结果，不过不同时间里面还会有大量重复碰撞 [chengmo@centos5 shell]$ date +%s%N 1287764807051101270 #这个可以说比较完美了，加入了时间戳，又加上了纳秒 通过上面说明，用它来做随机数的基数了，接下来我们看怎么样获得一段数据内怎么样获得随机数。 #!/bin/sh #写个随机函数，调用方法random min max #在min 与 max直接获得随机整数 #copyright chengmo QQ:8292669 #获得随机数返回值，shell函数里算出随机数后，更新该值 function random() { min=$1; max=$2-$1; num=$(date +%s+%N); ((retnum=num%max+min)); #进行求余数运算即可 echo $retnum; #这里通过echo 打印出来值，然后获得函数的，stdout就可以获得值 #还有一种返回，定义全价变量，然后函数改下内容，外面读取 } #得到1-10的seq数据项 for i in {1..10}; do out=$(random 2 10000); echo $i,"2-10000",$out; done; 看看运行结果： [chengmo@centos5 shell]\$ sh testrandom.sh\ 1,2-10000,5600 2,2-10000,5295 3,2-10000,3432 4,2-10000,3148 5,2-10000,9041 6,2-10000,4290 7,2-10000,2380 8,2-10000,9009 9,2-10000,5474 10,2-10000,3664 一个循环里面，得到值各不相同。 这个是我们常用方法，适应各种语言，是一个通用算法，就算服务器不提供，某时刻相同唯一数据标记，我们也可以通过这种方法，做自己的伪随机数。下面还有更简单方法呢，不要我们自己做了。 2、通过内部系统变量(\$RANDOM) 其实，linux已经提供有个系统环境变量了，直接就是随机数，哈哈，觉得刚学习方法，是不是白费了！！ [chengmo@centos5 shell]$ echo $RANDOM 10918 [chengmo@centos5 shell]$ echo $RANDOM 10001 #连续2次访问，结果不一样，这个数据是一个小于或等于5位的整数 可能有疑问了，如果超过5位的随机数怎么得到呢？ 呵呵，加个固定10位整数，然后进行求余，跟例1 一样了。接下来的例子又是我们自立更生做了。 3、通过系统内部唯一数据生成随机数（/dev/random,urandom) 我们知道dev目录下面，是linux一些默认设备，它给我们感觉就是放的是键盘，硬盘，光驱等设备的对应文件了。 其实linux有些设备很特殊，有特殊用途。前面我们说到的：/dev/[udp|tcp]/host/port比较特殊吧。呵呵，有扯远了。 /dev/random设备，存储着系统当前运行的环境的实时数据。它可以看作是系统某个时候，唯一值数据，因此可以用作随机数元数据。我们可以通过文件读取方式，读得里面数据。/dev/urandom这个设备数据与random里面一样。只是，它是非阻塞的随机数发生器，读取操作不会产生阻塞。 实例： [chengmo@centos5 shell]$ head -1 /dev/urandom ãÅ†ù…•KTþçanVÕã¹Û&¡õ¾“ô2íùU“ žF¦_ ÿ”†mEðûUráÏ=J¯TŸA•ÌAÚRtÓ #读一行，怎么是乱码呢？其实它是通过二进制数据保存实时数据的，那么我们怎么样把它变成整型数据呢？ [chengmo@centos5 ~/shell]$ head -200 /dev/urandom | cksum 1615228479 50333 #由于urandom的数据是非常多，不能直接通过cat读取，这里取前200行，其实整个数据都是变化的，取多少也一样是唯一的。 #cksum 将读取文件内容，生成唯一的表示整型数据，只有文件内容不变，生成结果就不会变化,与php crc函数 [chengmo@centos5 shell]$ head -200 /dev/urandom | cksum | cut -f1 -d" " 484750180 #cut 以” “分割，然后得到分割的第一个字段数据 得到整型数据，然后，类似一的方法就可以获得到随机数了。 题外话：在程序里面，我们经常md5得到唯一值，然后是字符串的，如果想表示成整型方式，可以通过crc函数.crc是循环冗余校验，相同数据通过运算，都会得到一串整型数据。现在这种验证应用很广。详细要了解，可以参考：crc. 下面还有个方法，直接从设备读取生成好的uuid码。 4、读取linux 的uuid码 在提到这个之前，有个概念，就是什么是uuid呢？ UUID码全称是通用唯一识别码 (Universally Unique Identifier, UUID),它 是一个软件建构的标准，亦为自由软件基金会 (Open Software Foundation, OSF) 的组织在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部份。 UUID 的目的，是让分布式系统中的所有元素，都能有唯一的辨识信息，而不需要通过中央控制端来做辨识信息的指定。如此一来，每个人都可以创建不与其它人冲突的 UUID。在这样的情况下，就不需考虑数据库创建时的名称重复问题。它会让网络任何一台计算机所生成的uuid码，都是互联网整个服务器网络中唯一的。它的原信息会加入硬件，时间，机器当前运行信息等等。 UUID格式是：包含32个16进位数字，以“-”连接号分为五段，形式为8-4-4-4-12的32个字符。范例；550e8400-e29b-41d4-a716-446655440000 ,所以：UUID理论上的总数为216 x 8=2128，约等于3.4 x 1038。 也就是说若每奈秒产生1兆个UUID，要花100亿年才会将所有UUID用完。 其实，大家做数据库设计时候，肯定听说过，guid(全局唯一标识符)码，它其实是与uuid类似，由微软支持。 这里编码，基本有操作系统内核产生。大家记得把，在windows里面，无论数据库，还是其它软件，很容易得到这个uuid编码。 linux 的uuid码 linux的uuid码也是有内核提供的，在/proc/sys/kernel/random/uuid这个文件内。其实，random目录，里面还有很多其它文件，都与生成uuid有关系的。 [chengmo@centos5 ~/shell]$ cat /proc/sys/kernel/random/uuid dff68213-b700-4947-87b1-d9e640334196 [chengmo@centos5 ~/shell]$ cat /proc/sys/kernel/random/uuid 7b57209a-d285-4fd0-88b4-9d3162d2e1bc #连续2次读取，得到的uuid是不同的 [chengmo@centos5 ~/shell]$ cat /proc/sys/kernel/random/uuid| cksum | cut -f1 -d" " 2141807556 #同上方法得到随机整数 这是linux下面，几种常见活动随机数整数方法，除了第一个是不同外，其实后3个，产生随机码的伪数据来源，都与/dev/random设备有关系。只是它们各自呈现不同而已。如果你还有更多其它方法，请给我消息，与大家分享 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/12/ 创建时间 2015-08-24 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
你是否在为手动连接很多服务器的终端Crt而烦恼呢？ Now 提供一个快捷的解决方法？ [1.批量创建SecureCRT的终端连接]\ [① 导出名称和IP的表格] ②将表格的转换为txt文件 serverlists.txt ③上传SecureCrt的模板配置文件 ④执行批量生成脚本 ⑤将该文件放到secureCrt的终端配置文件夹里面就可以看到了 终端配置文件查找图如下: 将ini文件丢到如上的文件夹即可。\ 批量创建ini文件脚本如下： #!/bin/bash #author: GaoMing #date: 2015-08-04 #qq: 530035210 #blog: https://my.oschina.net/pwd/blog #批量生成secureCrt终端连接 logdir=/data/log/shell #日志路径 log=$logdir/log.log #日志文件 is_font=1 #终端是否打印日志: 1打印 0不打印 is_log=0 #是否记录日志: 1记录 0不记录 file="serverlists.txt" iniFile="temp.ini" datef(){ date "+%Y-%m-%d %H:%M:%S" } print_log(){ if [[ $is_log -eq 1 ]];then [[ -d $logdir ]] || mkdir -p $logdir echo "[ $(datef) ] $1" >> $log fi if [[ $is_font -eq 1 ]];then echo -e "[ $(datef) ] $1" fi } autoCreateCrtConnect(){ print_log "开始读取服务器列表"、 if [[ ! -f $file ]];then print_log "$file文件不存在" fi if [[ ! -f $iniFile ]];then print_log "$iniFile文件不存在" fi print_log "开始批量生成ini文件" while read line do name=$(echo $line |awk -F':' '{print $1}') ip=$(echo $line |awk -F':' '{print $2}'|sed 's/[ ][ ]*//g') \cp $iniFile "$name".ini sed -i "s/8.8.8.8/$ip/g" "$name".ini print_log "生成$name.ini文件完成." done < $file print_log "开始批量生成ini文件完成" } autoCreateCrtConnect 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/56/ 创建时间 2015-08-04 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
Rexdeploy Rexdeploy: 一个基于名字服务自动化平台（命令行CLI版 和 API接口版） 中文文档 简单描述 RexDeploy是一个免客户端安装的管控平台，支持基于名字服务的自动发布，基于名字服务的自动重启(启动与停止)，以及基于名字服务的日志集中式管理，用户管理等，同时也支持批量执行命令，文件分发（上传与下载）等。 功能特点 批量命令执行 批量文件上传 批量文件下载 应用自动发布 应用自动回滚 应用自动重启 应用自动下载 配置自动下载 应用自动同步 应用命令执行 应用发布检查 支持并发执行 查看实时日志 集中日志下载 日志分析过滤 系统用户管理 应用灰度发布 微信和QQ消息 CLI部分截图 基于名字服务的应用自动发布 基于名字服务的应用灰度发布 基于名字服务的命令批量执行 基于名字服务的批量上传和下载 基于名字服务的应用批量重启 基于名字服务的批量日志下载 基于名字服务的批量日志过滤 基于服务器批量用户管理 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/31/ 创建时间 2015-06-04 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
expect定期远程登录Juniper防火墙实现定期重新拨号
#!/bin/bash #author: GaoMing #date: 2015-05-20 #qq: 530035210 #blog: https://my.oschina.net/pwd/blog #pppoe 定期重新拨号 logdir=/data/log/shell #日志路径 log=$logdir/log.log #日志文件 is_font=1 #终端是否打印日志: 1打印 0不打印 is_log=1 #是否记录日志: 1记录 0不记录 User=admin Host=192.168.1.253 Password="cccccc!@#xxxxxxxx748." #Cmd="get pppoe name ADSL-callcenter" Cmd="get interface" from_name="运维组" from="530035210@qq.com" to="huanggm@baoxian.com" datef(){ date "+%Y-%m-%d %H:%M:%S" } print_log(){ if [[ $is_log -eq 1 ]];then [[ -d $logdir ]] || mkdir -p $logdir echo "[ $(datef) ] $1" >> $log fi if [[ $is_font -eq 1 ]];then echo -e "[ $(datef) ] $1" fi } run() { if [[ $1 == "" ]];then print_log "cmd命令不能为空" exit fi expect -c " spawn /usr/bin/ssh -o StrictHostKeyChecking=no $User@$Host set timeout -1 expect \"\*password\*:\" send \"$Password\r\" expect \"\*\>\" send \"$1 \r\" expect \"\*\>\" send \"exit\r\" expect eof " } sendmail(){ email_title=$1 email_content=$2 email_subject=$3 if [[ $email_title == "" ]];then email_title="这是一封测试邮件." fi if [[ $email_content == "" ]];then email_content="这是测试邮件的内容." fi if [[ $email_subject == "" ]];then email_subject="这是测试邮件的主题." fi echo -e "To: \"${email_title}\" <${to}> \nFrom: \"${from_name}\" <${from}>\nSubject: ${email_subject}\n\n`echo ${email_content}`" | /usr/sbin/sendmail -t } #获取拨号前接口的外网地址 run_res1=$(run "get interface") interface_1=$(echo "$run_res1" |grep "eth0\/1" |awk '{print $2}' |sed "s/\/32//g") interface_2=$(echo "$run_res1" |grep "eth0\/2" |awk '{print $2}'|sed "s/\/32//g") interface_3=$(echo "$run_res1" |grep "eth0\/3" |awk '{print $2}'|sed "s/\/32//g") print_log "重启前,各接口的外网地址如下: eth0/1:$interface_1 eth0/2:$interface_2 eth0/3:$interface_3" #开始拨号 run_int1=$(run "exec pppoe name ADSL-bw2 disconnect") run_int2=$(run "exec pppoe name BW-GuangXian-2 disconnect") run_int3=$(run "exec pppoe name ADSL-callcenter disconnect") #获取拨号后接口的外网地址 run2_res1=$(run "get interface") interface2_1=$(echo "$run2_res1" |grep "eth0\/1" |awk '{print $2}' |sed "s/\/32//g") interface2_2=$(echo "$run2_res1" |grep "eth0\/2" |awk '{print $2}'|sed "s/\/32//g") interface2_3=$(echo "$run2_res1" |grep "eth0\/3" |awk '{print $2}'|sed "s/\/32//g") print_log "重启后,各接口的外网地址如下: eth0/1:$interface2_1 eth0/2:$interface2_2 eth0/3:$interface2_3" if [[ $interface2_1 == "" ]];then print_log "eth0/1: 拨号已经断开!" sendmail "" "eth0/1:重新拨号断开." "ppoe-eth1-重新拨号已经断开" fi if [[ $interface2_2 == "" ]];then print_log "eth0/2: 拨号已经断开!" sendmail "" "eth0/2:重新拨号断开." "ppoe-eth2-重新拨号已经断开" fi if [[ $interface2_3 == "" ]];then print_log "eth0/3: 拨号已经断开!" sendmail "" "eth0/3:重新拨号断开." "ppoe-eth3-重新拨号已经断开" fi if [[ $interface2_1 != "$interface_1" ]];then print_log "eth0/1:重新拨号成功!" else print_log "eth0/1:重新拨号失败,拨号前后外网IP没有发生变化!" sendmail "" "eth0/1:重新拨号失败,IP没有发生变化." "ppoe-eth1-重新拨号失败" fi if [[ $interface2_2 != "$interface_2" ]];then print_log "eth0/2:重新拨号成功!" else print_log "eth0/2:重新拨号失败,拨号前后外网IP没有发生变化!" sendmail "" "eth0/2:重新拨号失败,IP没有发生变化." "ppoe-eth2-重新拨号失败" fi if [[ $interface2_3 != "$interface_3" ]];then print_log "eth0/3:重新拨号成功!" else print_log "eth0/3:重新拨号失败,拨号前后外网IP没有发生变化!" sendmail "" "eth0/3:重新拨号失败,IP没有发生变化." "ppoe-eth3-重新拨号失败" fi 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/97/ 创建时间 2015-05-21 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
生产mongodb 分片与集群 方案 一、 mongodb分片与集群拓扑图 二、分片与集群的部署 1.Mongodb的安装 分别在以上3台服务器安装好mongodb 安装方法见安装脚本。 2.Mongod 创建单个分片的副本集 10.68.4.209 ①建立数据文件夹和日志文件夹 mdkir /data/{master,slave,arbiter} mkdir /data/log/mongodb/{master,slave,arbiter} -p ②建立配置文件 master.conf dbpath=/data/master logpath=/data/log/mongodb/master/mongodb.log pidfilepath=/var/run/mongo_master.pid directoryperdb=true logappend=true replSet=policydb port=10002 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 slave.conf dbpath=/data/slave logpath=/data/log/mongodb/slave/mongodb.log pidfilepath=/var/run/mongo_slave.pid directoryperdb=true logappend=true replSet=policydb port=10001 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 arbiter.conf dbpath=/data/arbiter logpath=/data/log/mongodb/arbiter/mongodb.log pidfilepath=/var/run/mongo_arbiter.pid directoryperdb=true logappend=true replSet=policydb port=10000 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 ③启动mongodb /etc/init.d/mongodb_master start /etc/init.d/mongodb_slave start /etc/init.d/mongodb_arbiter start ④配置主、备、仲裁节点 主节点: /usr/local/mongodb/bin/mongo 10.68.4.209:10002 MongoDB shell version: 2.4.9 connecting to: 10.68.4.209:10002/test use admin switched to db admin config={ _id:"policydb", members:[ {_id:0,host:'10.68.4.209:10002',priority:2}, {_id:1,host:'10.68.4.209:10001',priority:1}, ... {_id:2,host:'10.68.4.209:10000',arbiterOnly:true}] }; { "_id" : "policydb", "members" : [ { "_id" : 0, "host" : "10.68.4.209:10002", "priority" : 2 }, { "_id" : 1, "host" : "10.68.4.209:10001", "priority" : 1 }, { "_id" : 2, "host" : "10.68.4.209:10000", "arbiterOnly" : true } ] } rs.initiate(config) #初始化 rs.status() #查看集群状态 10.68.4.29 ①建立数据文件夹和日志文件夹 mdkir /data/{master,slave,arbiter} mkdir /data/log/mongodb/{master,slave,arbiter} -p ②建立配置文件 master.conf dbpath=/data/master logpath=/data/log/mongodb/master/mongodb.log pidfilepath=/var/run/mongo_master.pid directoryperdb=true logappend=true replSet=policydb2 port=10002 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 slave.conf dbpath=/data/slave logpath=/data/log/mongodb/slave/mongodb.log pidfilepath=/var/run/mongo_slave.pid directoryperdb=true logappend=true replSet=policydb2 port=10001 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 arbiter.conf dbpath=/data/arbiter logpath=/data/log/mongodb/arbiter/mongodb.log pidfilepath=/var/run/mongo_arbiter.pid directoryperdb=true logappend=true replSet=policydb2 port=10000 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 ③启动mongodb /etc/init.d/mongodb_master start /etc/init.d/mongodb_slave start /etc/init.d/mongodb_arbiter start ④配置主、备、仲裁节点 主节点: /usr/local/mongodb/bin/mongo 10.68.4.209:10002 MongoDB shell version: 2.4.9 connecting to: 10.68.4.209:10002/test use admin switched to db admin config={ _id:"policydb2", members:[ {_id:0,host:'10.68.4.29:10002',priority:2}, {_id:1,host:'10.68.4.29:10001',priority:1}, ... {_id:2,host:'10.68.4.209:10000',arbiterOnly:true}] }; { "_id" : "policydb", "members" : [ { "_id" : 0, "host" : "10.68.4.29:10002", "priority" : 2 }, { "_id" : 1, "host" : "10.68.4.29:10001", "priority" : 1 }, { "_id" : 2, "host" : "10.68.4.29:10000", "arbiterOnly" : true } ] } rs.initiate(config) #初始化 rs.status() #查看集群状态 10.68.4.30 ①建立数据文件夹和日志文件夹 mdkir /data/{master,slave,arbiter} mkdir /data/log/mongodb/{master,slave,arbiter} -p ②建立配置文件 master.conf dbpath=/data/master logpath=/data/log/mongodb/master/mongodb.log pidfilepath=/var/run/mongo_master.pid directoryperdb=true logappend=true replSet=policydb3 port=10002 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 slave.conf dbpath=/data/slave logpath=/data/log/mongodb/slave/mongodb.log pidfilepath=/var/run/mongo_slave.pid directoryperdb=true logappend=true replSet=policydb3 port=10001 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 arbiter.conf dbpath=/data/arbiter logpath=/data/log/mongodb/arbiter/mongodb.log pidfilepath=/var/run/mongo_arbiter.pid directoryperdb=true logappend=true replSet=policydb3 port=10000 oplogSize=10000 fork=true noprealloc=true profile=1 slowms=200 ③启动mongodb /etc/init.d/mongodb_master start /etc/init.d/mongodb_slave start /etc/init.d/mongodb_arbiter start ④配置主、备、仲裁节点 主节点: /usr/local/mongodb/bin/mongo 10.68.4.209:10002 MongoDB shell version: 2.4.9 connecting to: 10.68.4.209:10002/test use admin switched to db admin config={ _id:"policydb3", members:[ {_id:0,host:'10.68.4.30:10002',priority:2}, {_id:1,host:'10.68.4.30:10001',priority:1}, ... {_id:2,host:'10.68.4.30:10000',arbiterOnly:true}] }; { "_id" : "policydb", "members" : [ { "_id" : 0, "host" : "10.68.4.30:10002", "priority" : 2 }, { "_id" : 1, "host" : "10.68.4.30:10001", "priority" : 1 }, { "_id" : 2, "host" : "10.68.4.30:10000", "arbiterOnly" : true } ] } rs.initiate(config) #初始化 rs.status() #查看集群状态 2.Mongod 创建单个分片的配置服务器 ① 创建配置目录 10.68.4.209 mkdir /data/config 10.68.4.29 mkdir /data/config 10.68.4.30 mkdir /data/config ②准备配置服务器的配置文件 3个服务器的配置服务器的配置文件一致 config.conf dbpath=/data/config logpath=/data/log/mongodb/config/mongodb.log pidfilepath=/var/run/mongo_config.pid directoryperdb=true logappend=true port=10003 fork=true configsvr=true ③启动配置服务器 /etc/init.d/mongodb_config start 3.Mongod 创建并配置mongos和开启分片模式 ① 创建日志目录 Mkdir -p /data/log/mongodb/mongos/ ② 准备mongos的配置文件 mongos.conf logpath=/data/log/mongodb/mongos/mongodb.log pidfilepath=/var/run/mongo_mongos.pid logappend=true port=10004 fork=true configdb=10.68.4.209:10003,10.68.4.29:10003,10.68.4.30:1000 ③ 启动mongos /etc/init.d/mongodb_mongos start ④ 配置分片 sh.addShard("policydb/10.68.4.209:10002") sh.addShard("policydb2/10.68.4.29:10002") sh.addShard("policydb3/10.68.4.30:10002") sh.enableSharding("policydb") db.runCommand({"shardcollection":"policydb.fullPolicyTextInfo_history", "key":{"key":1}}) db.printShardingStatus() #查看分片状态 sh.status({verbose:true}) sh.status() 3.快速创建副本集和配置服务脚本 上图 1.图1 2.图2 config.conf配置文件 3.图3 附mongodb一键安装脚本: http://pan.baidu.com/s/1c0zvP7M 附mongodb副本集和配置服务器一键配置脚本: http://pan.baidu.com/s/1GuQ0A 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/68/ 创建时间 2015-05-06 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
Converting slapd.conf to a Directory Based Configu
OpenLDAP 2.4 OpenLDAP 2.4 provides some great new features over 2.3. Notable among them are the ability to store configuration data in the directory and change values on the fly. Adding a Schema Converting slapd.conf to a Directory Based Configuration OpenLDAP 2.4 maintains an LDIF-based online directory in /etc/openldap/slapd.d/ (or otherwise specified location). In order to use this, you must seed the directory one of two ways. One way is to convert an existing slapd.conf file, which is illustrated below. Note that to access the newly minted cn=config, you should create an entry in your slapd.conf to provide a root password to this entry, or otherwise provide a useful ACL/ACI which gives a user access. To convert a standard slapd.conf file to the new format, issue the following command (re: man slapd-config): slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d Note that the directory /etc/openldap/slapd.d must exist prior to this command successfully completing. After importing the config file, start the OpenLDAP server: /etc/init.d/ldap start Verify that the server is running: ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts After validating that the server will start and stop, import some data with an LDIF file: slapadd -l <file>.ldif When attempting this, I get an error about an invalid attribute for an objectclass: # slapadd -l slapcat.out str2entry: invalid value for attributeType objectClass #1 (syntax 1.3.6.1.4.1.1466.115.121.1.38) slapadd: could not parse entry (line=1) Missing a schema, had to add cosine schema to get this to work. When attempting to add the schema ldif, I get this error: # ldapadd -x -H ldap://locahost -D "cn=manager,dc=example,dc=org" -W -f core.ldif Enter LDAP Password: ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1) I switched back to using the slapd.conf file to get this to work, and emptying out the /var/lib/openldap-data directory, reattempting the slapadd, I get the following: # slapadd -l backup.ldif bdb_db_open: warning - no DB_CONFIG file found in directory /var/lib/openldap-data: (2). Expect poor performance for suffix "dc=example,dc=org". <= str2entry: str2ad(pwdHistory): attribute type undefined slapadd: could not parse entry (line=79) Missing ppolicy overlay. `` Adding some schemas: # ldapadd -x -H ldap://localhost/ -D "cn=config" -W -f schema/archive/cosine.ldif Enter LDAP Password: adding new entry "cn=cosine,cn=schema,cn=config" # ldapadd -x -H ldap://localhost/ -D "cn=config" -W -f schema/archive/inetorgperson.ldif Enter LDAP Password: adding new entry "cn=inetorgperson,cn=schema,cn=config" # ldapadd -x -H ldap://localhost/ -D "cn=config" -W -f schema/archive/nis.ldif Enter LDAP Password: adding new entry "cn=nis,cn=schema,cn=config" # ldapadd -x -H ldap://localhost/ -D "cn=config" -W -f schema/archive/openldap.ldif Enter LDAP Password: adding new entry "cn=openldap,cn=schema,cn=config" `` Note that you cannot (as of version 2.4.7) use slapindex to generate the cn=config configuration, use slaptest: # cd /etc/openldap # mkdir slapd.d # /usr/sbin/slapindex -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d # echo $? 0 Program exits without error. # ls /etc/openldap/slapd.d Subsequently, running this command immediately after generates the appropriate cn=config: # slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d config file testing succeeded # ll slapd.d total 8 drwxr-x--- 4 root root 4096 Jan 10 13:07 cn=config -rw------- 1 root root 1097 Jan 10 13:07 cn=config.ldif I have filed an ITS with the OpenLDAP project for this (ITS#5321). `` Querying cn=config A sample query: ldapsearch -x -H ldap://localhost/ -D "cn=config" -b 'cn=config' -W cn=config Enter LDAP Password: # extended LDIF # # LDAPv3 # base <cn=config> with scope subtree # filter: cn=config # requesting: ALL # # config dn: cn=config objectClass: olcGlobal cn: config olcConfigFile: /etc/openldap/slapd.conf.WORKING olcConfigDir: /etc/openldap/slapd.d olcArgsFile: /var/run/openldap/run/slapd.args olcAttributeOptions: lang- olcAuthzPolicy: none olcConcurrency: 0 olcConnMaxPending: 100 olcConnMaxPendingAuth: 1000 olcGentleHUP: FALSE olcIdleTimeout: 0 olcIndexSubstrIfMaxLen: 4 olcIndexSubstrIfMinLen: 2 olcIndexSubstrAnyLen: 4 olcIndexSubstrAnyStep: 2 olcLocalSSF: 71 olcLogLevel: Any olcPidFile: /var/run/openldap/run/slapd.pid olcReadOnly: FALSE olcSaslSecProps: noplain,noanonymous olcSockbufMaxIncoming: 262143 olcSockbufMaxIncomingAuth: 16777215 olcThreads: 16 olcToolThreads: 1 # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 `` Query cn=schema: ldapsearch -x -H ldap://localhost/ -D "cn=config" -b 'cn=schema,cn=config' -W `` Query cn=config for olcDatabase entries: Note that this searches for the second database, which is of type bdb. ldapsearch -x -H ldap://localhost/ -D "cn=config" -b 'olcDatabase={1}bdb,cn=config' -W -LLL `` 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/46/ 创建时间 2015-03-13 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
[ ]设置IP、DNS、网关 >netsh interface ip set address name="本地连接" source=static addr=192.168.132.5 mask=255.255.255.0 >netsh interface ip set address name="本地连接" gateway=192.168.132.1 gwmetric=0 >netsh interface ip set dns name="本地连接" source=static addr=192.168.132.1 register=PRIMARY >netsh interface ip set wins name="本地连接" source=static addr=none [ ]查看IP、DNS、网关 >netsh interface ip show address ****\ 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/30/ 创建时间 2015-03-12 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools
cmd命令批量修改文件名: (批量去掉下载电影后的前缀) @echo off for /f "delims=" %%a in ('dir /b/s/a-d [阳光电影www.ygdy8.com].*') do ( set "str=%%~nxa" setlocal enabledelayedexpansion ren "%%a" "!str:~20!" endlocal ) 批量删除文件名特定字符(含特定字符自身)前后的文字? (如:Movie_20_(528990).mpg,要求只保留528990.mpg这样的文件名) @echo off for %%a in (*.mpg) do for /f "tokens=2 delims=()" %%b in ("%%a") do ren "%%a" "%%b.mpg" 批量添加文件名前缀 @echo off&setlocal EnableDelayedExpansion color 0a echo %date% %time% echo 正在批量重命名文件...... set a=1 for /f "delims=" %%i in ('dir /b *.del') do ( ren "%%i" "文件名前缀%%i" set /a a+=1 ) ) set /a a-=1 echo 重命名完成，共重命名%a%个文件。 pause 文章作者 明哥 文章地址 https://www.pvcreate.com/index.php/archives/70/ 创建时间 2015-02-18 关注订阅 微信订阅号 开源项目 https://gitee.com/lookingdreamer 工具市场 https://gitee.com/lookingdreamer/SPPPOTools