Skip to content Skip to main navigation Skip to footer

shell 脚本

Linux系统下find命令递归删除查找目录的方法

本文将会讲述如何使用linux系统下的find查找命令来查找目录或文件,并将查找到的所有文件和目录递归删除掉。

Linux find 命令递归删除非空目录

通常情况下我们会想到find命令里的删除操作是使用-delete选项,但是使用该选项只能删除空目录的文件,不能递归删除该目录里的其它文件。如下面的例子:

$ ls dir1
test1
$ find ./ -name "dir1" -type d -delete
find: cannot delete `./dir1': Directory not empty

可以使用下面的Linux find 命令删除非空目录,如:

$ find ./ -name “dir1” -type d -exec rm -rf {} +

或者

$ find ./ -name “dir1” -type d -exec rm -rf  \;

Linux find 命令结合xargs命令实现删除非空目录

删除当前目录下的所有空目录

$ find ./ -type d -empty -print0 |xargs -0 -i {} rm -rf  “{}”

删除当前目录下所有以“dir”开头的目录

$ find ./ -type d -name “dir*” -print0 |xargs -0 -I {} rm -rf “{}”

 

Linux系统下通过bash shell脚本实现倒计时的方法

本文主要讲述如何在linux系统下通过bash shell 脚本来实现在屏幕上输出倒计时的方法。
先来看看实现后的脚本,如下:

#!/bin/bash
 # script name: ctimer.sh
 # Author: osetc.com
 # --------------------------------------------------------
row=2
 col=2
 countdown() {
 msg="starting..."
 clear
 tput cup $row $col
 echo -n "$msg"
 l=${#msg}
 l=$(( l+$col ))
 for i in {30..1}
 do
     tput cup $row $l
     echo -n "$i"
     sleep 1
 done
 }
 countdown

首先我们定义了一个名为countdown的shell 函数,在函数里定义了一个msg变量用于在屏幕上显示倒计时信息,clear 命令用于清除屏幕上的历史输出信息,tput cut 命令用于设置屏幕输出信息的位置,最后通过for循环来实现倒计时,并更新输出信息的位置。
执行上面的脚本

$bash ctimer.sh
 Starting...30

 

Linux系统下批量升级LXD容器里的虚拟机的方法

本文将会讲述如何在linux 系统下自动升级LXD容器里的所有的虚拟机。
下面我们通过两种方法实现自动升级所有虚拟机:

方法一:使用shell 脚本来升级

手动的升级命令是:

/usr/bin/lxc exec 虚拟机名 -- /usr/bin/apt-get -y upgrade (ubuntu系统)
/usr/bin/lxcexec 虚拟机名  -- /usr/bin/yum -y update    (centos 系统)

下面来创建bash shell 脚本来自动升级所有的虚拟机:

#!/bin/bash
#脚本名:vmUpgrade.sh
#--------------------------------
cmd="[email protected]"for i in 虚机1 虚机2 虚机3 虚机4
do
echo "[*** $i ***]"
/usr/bin/lxc exec $i -- $cmd
done

下面就可以调用脚本来升级vm了,执行下面的命令:
Ubuntu 系统:

$ ./vmUpgrade.sh /usr/bin/apt-get update
$ ./vmUpgrade.sh /usr/bin/apt-get -y upgrade

Centos 系统:

$ ./vmUpgrade.sh /usr/bin/yum -y update

方法二:使用Ansible 自动化工具

1# 安装ansible 工具
执行命令:

$ sudo apt-get install ansible

命令输出:

正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
下列软件包是自动安装的并且现在不需要了:
gyp javascript-common libjs-inherits libjs-jquery libjs-node-uuid libjs-underscore libnvpair1linux libssl-dev libssl-doc libuutil1linux libuv1-dev
libzfs2linux libzpool2linux zfs-doc zlib1g-dev
使用'apt autoremove'来卸载它(它们)。
将会同时安装下列软件:
ieee-data libyaml-0-2 python-crypto python-ecdsa python-httplib2 python-jinja2 python-markupsafe python-netaddr python-paramiko python-selinux
python-six python-yaml
建议安装:
sshpass python-crypto-dbg python-crypto-doc python-jinja2-doc ipython python-netaddr-docs
下列【新】软件包将被安装:
ansible ieee-data libyaml-0-2 python-crypto python-ecdsa python-httplib2 python-jinja2 python-markupsafe python-netaddr python-paramiko python-selinux
python-six python-yaml
升级了 0 个软件包,新安装了 13 个软件包,要卸载 0 个软件包,有 5 个软件包未被升级。
需要下载 2,903 kB 的归档。
解压缩后会消耗 17.6 MB 的额外空间。
您希望继续执行吗? [Y/n] y
获取:1 http://archive.ubuntu.com/ubuntu xenial/main amd64 libyaml-0-2 amd64 0.1.6-3 [47.6 kB]
获取:2 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 python-crypto amd64 2.6.1-6ubuntu0.16.04.2 [246 kB]
获取:3 http://archive.ubuntu.com/ubuntu xenial/main amd64 python-markupsafe amd64 0.23-2build2 [15.5 kB]
获取:4 http://archive.ubuntu.com/ubuntu xenial/main amd64 python-jinja2 all 2.8-1 [109 kB]
获取:5 http://archive.ubuntu.com/ubuntu xenial/main amd64 python-six all 1.10.0-3 [10.9 kB]
获取:6 http://archive.ubuntu.com/ubuntu xenial/main amd64 python-ecdsa all 0.13-2 [34.0 kB]
获取:7 http://archive.ubuntu.com/ubuntu xenial/main amd64 python-paramiko all 1.16.0-1 [109 kB]
获取:8 http://archive.ubuntu.com/ubuntu xenial/main amd64 python-yaml amd64 3.11-3build1 [105 kB]
获取:9 http://archive.ubuntu.com/ubuntu xenial/main amd64 python-httplib2 all 0.9.1+dfsg-1 [34.2 kB]
获取:10 http://archive.ubuntu.com/ubuntu xenial/main amd64 ieee-data all 20150531.1 [830 kB]
获取:11 http://archive.ubuntu.com/ubuntu xenial/main amd64 python-netaddr all 0.7.18-1 [174 kB]
获取:12 http://archive.ubuntu.com/ubuntu xenial-updates/universe amd64 ansible all 2.0.0.2-2ubuntu1 [1,016 kB]
获取:13 http://archive.ubuntu.com/ubuntu xenial/universe amd64 python-selinux amd64 2.4-3build2 [173 kB]
已下载 2,903 kB,耗时 10秒 (287 kB/s)
正在选中未选择的软件包 libyaml-0-2:amd64。
(正在读取数据库 ... 系统当前共安装有 69061 个文件和目录。)
正准备解包 .../libyaml-0-2_0.1.6-3_amd64.deb  ...
正在解包 libyaml-0-2:amd64 (0.1.6-3) ...
正在选中未选择的软件包 python-crypto。
正准备解包 .../python-crypto_2.6.1-6ubuntu0.16.04.2_amd64.deb  ...
正在解包 python-crypto (2.6.1-6ubuntu0.16.04.2) ...
正在选中未选择的软件包 python-markupsafe。
正准备解包 .../python-markupsafe_0.23-2build2_amd64.deb  ...
正在解包 python-markupsafe (0.23-2build2) ...
正在选中未选择的软件包 python-jinja2。
正准备解包 .../python-jinja2_2.8-1_all.deb  ...
正在解包 python-jinja2 (2.8-1) ...
正在选中未选择的软件包 python-six。
正准备解包 .../python-six_1.10.0-3_all.deb  ...
正在解包 python-six (1.10.0-3) ...
正在选中未选择的软件包 python-ecdsa。
正准备解包 .../python-ecdsa_0.13-2_all.deb  ...
正在解包 python-ecdsa (0.13-2) ...
正在选中未选择的软件包 python-paramiko。
正准备解包 .../python-paramiko_1.16.0-1_all.deb  ...
正在解包 python-paramiko (1.16.0-1) ...
正在选中未选择的软件包 python-yaml。
正准备解包 .../python-yaml_3.11-3build1_amd64.deb  ...
正在解包 python-yaml (3.11-3build1) ...
正在选中未选择的软件包 python-httplib2。
正准备解包 .../python-httplib2_0.9.1+dfsg-1_all.deb  ...
正在解包 python-httplib2 (0.9.1+dfsg-1) ...
正在选中未选择的软件包 ieee-data。
正准备解包 .../ieee-data_20150531.1_all.deb  ...
正在解包 ieee-data (20150531.1) ...
正在选中未选择的软件包 python-netaddr。
正准备解包 .../python-netaddr_0.7.18-1_all.deb  ...
正在解包 python-netaddr (0.7.18-1) ...
正在选中未选择的软件包 ansible。
正准备解包 .../ansible_2.0.0.2-2ubuntu1_all.deb  ...
正在解包 ansible (2.0.0.2-2ubuntu1) ...
正在选中未选择的软件包 python-selinux。
正准备解包 .../python-selinux_2.4-3build2_amd64.deb  ...
正在解包 python-selinux (2.4-3build2) ...
正在处理用于 man-db (2.7.5-1) 的触发器 ...
正在设置 libyaml-0-2:amd64 (0.1.6-3) ...
正在设置 python-crypto (2.6.1-6ubuntu0.16.04.2) ...
正在设置 python-markupsafe (0.23-2build2) ...
正在设置 python-jinja2 (2.8-1) ...
正在设置 python-six (1.10.0-3) ...
正在设置 python-ecdsa (0.13-2) ...
正在设置 python-paramiko (1.16.0-1) ...
正在设置 python-yaml (3.11-3build1) ...
正在设置 python-httplib2 (0.9.1+dfsg-1) ...
正在设置 ieee-data (20150531.1) ...
正在设置 python-netaddr (0.7.18-1) ...
正在设置 ansible (2.0.0.2-2ubuntu1) ...
正在设置 python-selinux (2.4-3build2) ...
正在处理用于 libc-bin (2.23-0ubuntu9) 的触发器 ...

2# 创建一个yml个格式的ansible playbook 文件(update.yml),加入下面的内容

# Update host running on Debian/Ubuntu
- name: Updating host using apt
apt:
update_cache: yes
upgrade: dist
#
# Now update VMs powered by Debian/Ubuntu Linux
#
- name: Run lxc to update debian/ubuntu vms repo
command: /usr/bin/lxc exec {{ item }} -- /usr/bin/apt-get -y update
with_items:
- ubuntuvm1
- debianvm2
- ubuntuvm3
- name: Run lxc to upgrade debian/ubuntu vms pacakges
command: /usr/bin/lxc exec {{ item }} -- /usr/bin/apt-get -y upgrade
with_items:
- ubuntuvm1
- debianvm2
- ubuntuvm3
#
# Now update VMs powered by CentOS 7 Linux
#
- name: Run lxc to upgrade centos vms
command: /usr/bin/lxc exec {{ item }} -- /usr/bin/yum -y update
with_items:
- centosvm4
- centosvm5
- centosvm6

3# 执行下面的ansible-playbook命令,执行升级操作

$ ansible-playbook -i /etc/ansible/hosts update.yml

 

Linux系统下删除包含特定字符或数字的方法

本文将会讲述如何在linux 系统下通过删除rm命令来删除包含特定字符或数字的方法。本文主要针对linux初学者。
在linux下面删除文件或目录的命令是rm, 如果想删除特定模式的文件或者目录,那么就需要使用linux命令中特有的通配符。
比如下面的几个通配符模式:
* : 可以匹配任意字符串
*b*: 可以匹配包含字符”b”的任意字符串
*2*: 可以匹配包含数字”2”的任意字符串
*.[ab]: 可以匹配任意以字母a 或b 结尾的字符串
*[cd]*:可以匹配包含字母‘c’或 ‘d’的任意字符串
: 可以匹配任意一个单一字符

实例:

显示出当前目录下所有的以包含test 的文件

$ ls *test*
test2  test30  test5

显示以数字1结尾的文件

$ ls *1
text1

显示所有以“test”开头的文件

$ ls test*
test2  test30  test5

删除所有以“test”开头的文件

$ rm -v test*
removed 'test2'
removed 'test30'
removed 'test5'

 
 

shell:BASH 的目录切换

By WEN Pingbo ofTinyLab.org

2015/06/02

在 BASH 中你用的最多的命令是什么?这绝对非 cd 莫属(ls 也是个潜力股,暂时做老二吧)。所以在这篇文章中,我们聊聊如何高效的在 BASH 中切换目录。

往后切换目录

回退目录,正规的做法是 cd ..。但网上的小伙伴很有才,发明了更简洁实用的命令。这里把它搬过来,其实我自己也一直这么用的:

alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'

甚至可以定义5点的别名,但感觉用到的几率不大。有了这些别名,就可以愉快的用 N 个点来回退 N 级目录。

其实在进行目录切换时,BASH 默认会把上一个目录记录在 OLDPWD。可以用 cd –,或者 cd $OLDPWD来在两个目录之间来回切换。这在两个不同的目录树下,很有作用。

往前切换目录

进入指定的目录,这个没什么特别的技巧了。老老实实用 cd /path/to/dir来做吧。虽然目的地咱不能省,还是可以偷点懒的。

CDPATH

我们可以利用 CDPATH 定义 cd命令的 base 目录,然后就可以直达目的地,而不用在前面加一堆父目录。比如:

vim: BASH 的目录切换
vim: BASH 的目录切换

不过这个方法不是很灵活,且有副作用。前段时间,我机器上编译 Android,死活过不去,最后发现是这货搞的鬼。所以,玩玩可以,在生产环境慎用!

CDSPELL

在 BASH 中打开 cdspell( shopt -s cdspell),可以在你目标目录写错的时候,BASH 能自动帮你矫正,省了重新敲一遍。效果如下:

vim: BASH 的目录切换
vim: BASH 的目录切换

这个还是很有用的,建议打开。

目录堆栈

前面讲的大多数是两个目录之间的切换,我们可以简单的用一个变量 OLDPWD 来记录。如果涉及到多个目录,为了记录之前目录切换的历史记录,就得另起一套机制了。而 BASH 就为我们提供了这样一套机制 – “目录堆栈(dirs/pushd/popd)”。其运行机制就是一个堆栈,先进先出。我们可以用 pushd dir来 push 对应的目录路径,用 popd来弹出栈顶的目录,用 dirs可以查看当前堆栈的内容。这个堆栈,在各个 BASH 实例之间是不通用的。也就是说在当前 BASH 中 push 的目录,不会影响其他 BASH。每开一个 BASH,都会初始化一个这样的堆栈。

有的时候,在脚本中需要临时保存当前工作路径,以便回溯。这个时候就可以利用这个目录堆栈了。

模拟 Windows Explorer (icd)

之前,我一直纠结在为什么 BASH 只能记录两层目录。当你的工作目录层数比较多的时候,你经常需要多次 cd ..来把工作目录回退 A 目录,然后又要进入 B 目录,再进入 C 目录,最后还要回到 A 目录。尽管前面已经偷了很多懒,还是显得很繁琐。而我的想法是把 Windows 的文件浏览器中前进和后退功能添加到 BASH 中,就像 nautilus 和 各大浏览器做的那样。

为了实现这种效果,首先得记录每次进入的目录路径。这个 BASH 自带的目录堆栈可以做,但是 BASH 在 popd 之后,就把栈顶的路径删除了。这样就导致后退后,无法再前进了。所以得额外定义一套机制来保存目录记录。这里我用一个文件来存放,文件的第一行是记录的路径总数,第二行是当前所在的目录位置,而之后的的每一行就代表一条目录记录。比如:

3
2
/home
/home/wenpingbo
/var/log

这样,后退可以到 /home,前进可以到 /var/log。另外,为了保证各个 BASH 之间互不干扰,还得引入 session 这个概念。还是直接为每一个 BASH 创建这样一个文件,放在 /tmp下,文件名就以 BASHPID 为后缀,避免重名。

逻辑上,得实现 3 个函数 icd_mainicd_backwardicd_forward,用于进入新目录、后退、前进。然后定义快捷键绑定到这 3 个函数,来实现相应的功能。我自己是这样绑定的:

alias cd=icd_main
alias h=icd_backward
alias l=icd_forward
# Ctrl + right
bind '"e[1;5D>":"hn>"'
# Ctrl + left
bind '"e[1;5C>":"ln>"' 

这样,就可以用 h/ Ctrl-right来回退, l/ Ctrl-left来前进, cd来做正常的目录改变。一起来看一下效果:

vim: BASH 的目录切换
vim: BASH 的目录切换

对应的源码,可以在这找到 icd src

~原创有您,更持久!期待您的支持~

vim: BASH 的目录切换
vim: BASH 的目录切换

0 0

原文:http://www.tinylab.org/bash-directory-change/

BASH 的调试手段

By WEN Pingbo ofTinyLab.org

2015/06/01

平时在写 BASH 脚本时,总是会碰到让人抓狂的 BUG。和 C/C++ 这么丰富的调试工具相比,BASH 又有什么调试手段呢?

echo/print (普通技)

打印一些变量,或者提示信息。这应该是一个通用的方法了。在 BASH 里,我们可以简单的用 echo,或者 print 来输出一些 log,或者加一些 loglevel 来过滤一些 log。这里贴一下我平常用的函数:

_loglevel=2
DIE() {
    echo "Critical: $1>" >&2
    exit 1
}
INFO() {
    [ $_loglevel -ge 2 ] && echo "INFO: $1>" >&2
}
ERROR() {
    [ $_loglevel -ge 1 ] && echo "ERROR: $1>" >&2
} 

这里的实现只是简单的加了一个 loglevel,其实可以把 log 输出到一个文件中,或者给 log 加上颜色。比如:

# add color
[ $_loglevel -ge 1 ] && echo -e "33[31m ERROR:33[0m $1>" >&2
# redirect to file
[ $_loglevel -ge 1 ] && echo "ERROR: $1>" > /var/log/xxx_log.$BASHPID 

set -x (稀有技)

-x(xtrace) 选项会导致 BASH 在执行命令之前,先把要执行的命令打印出来。这个选项对调试一些命令错误很有帮助。

有的时候,由于传进来的参数带有一些特殊字符,导致 BASH 解析时不是按照我们预想的进行。这个时候,把 -x 打开,就能在命令执行前,把扩展后的命令打印出来。比如基于前面写的函数:

set -x
INFO "this is a info log>"
ERROR "this is a error log>"
set +x 

然后就可以看到如下输出:

+ INFO 'this is a info log'
+ '[' 2 -ge 2 ']'
+ echo -e '33[32m INFO:33[0m this is a info log'
 INFO: this is a info log
+ ERROR 'this is a error log'
+ '[' 2 -ge 1 ']'
+ echo -e '33[33m ERR:33[0m this is a error log'
 ERR: this is a error log
+ set +x 

如果想全程打开 xtrace,可以在执行脚本的时候加 -x参数。

trap/bashdb (史诗技)

为了方便调试,BASH 也提供了陷阱机制。这跟之前介绍的两种方法高级不少。我们可以利用 trap 这个内置命令来指定各个 sigspec 应该执行的命令。trap 的具体用法如下:

trap [-lp] [[arg] sigspec ...]

sigspec 包括 中定义的各个 signal, EXIT,ERR,RETURN 和 DEBUG。

各个 signal 这里就不介绍了。EXIT 会在 shell 退出时执行指定的命令。若当前 shell 中有命令执行返回非零值,则会执行与 ERR 相关联的命令。而 RETURN 是针对 source.,每次执行都会触发 RETURN 陷阱。若绑定一个命令到 DEBUG,则会在每一个命令执行之前,都会先执行 DEBUG 这个 trap。这里要注意的是,ERR 和 DEBUG 只在当前 shell 有效。若想函数和子 shell 自动继承这些 trap,则可以设置 -T(DEBUG/RETURN) 和 -E(ERR)。

比如,下面的脚本会在退出时,执行echo:

#!/bin/bash
trap "echo this is a exit echo>" EXIT
echo "this is a normal echo>" 

或者,让脚本中命令出错时,把相应的命令打印出来:

#!/bin/bash
trap 'echo $BASH_COMMAND return err' ERR
echo this is a normal test
UnknownCmd 

这个脚本的输出如下:

this is a normal test
tt.sh: line 6: UnknownCmd: command not found
UnknownCmd return err 

亦或者,让脚本的命令单步执行:

#!/bin/bash
trap '(read -p "[$0 : $LINENO] $BASH_COMMAND ?>")' DEBUG
echo this is a test
i=0
while [ true ]
do
    echo $i
    ((i++))
done 

其输出如下:

[tt.sh : 5] echo this is a test ?
this is a test
[tt.sh : 7] i=0 ?
[tt.sh : 8] [ true ] ?
[tt.sh : 10] echo $i ?
[tt.sh : 11] ((i++)) ?
[tt.sh : 8] [ true ] ?
[tt.sh : 10] echo $i ?
1
[tt.sh : 11] ((i++)) ?
[tt.sh : 8] [ true ] ?
[tt.sh : 10] echo $i ?
2
[tt.sh : 11] ((i++)) ? 

是不是有点意思了?其实有一个 bashdb的开源项目,也是利用 trap 机制,模拟 gdb 做了一个 bash 脚本的调试器。它本身也是一个 bash 脚本。在加载要调试的脚本后,可以用和 gdb 类似的命令,甚至缩写也是一样的,大家可以尝试一下:)

(上个月沉迷于 Diablo3,最后发现自己脸不行,悴!还是回来写点东西吧!)

~原创有您,更持久!期待您的支持~

BASH 的调试手段
BASH 的调试手段

0 0

原文:http://www.tinylab.org/bash-debugging-tools/

Nginx服务启动、停止和重启等操作的SHELL脚本

由于使用源码编译安装Nginx,不会像yum install那样自动生成Nginx服务控制脚本,所以需要自己添加一个操作脚本。谷歌上搜了一下,shell脚本的代码基本类似,因此自己稍微整理改动了下。

下面的shell脚本内容,需要根据Nginx实际编译安装的配置,修改 NGINX_CONF_FILE=”/etc/nginx/nginx.conf>”lockfile=/var/lock/nginx.lock这两个参数(即前文 《2015博客升级记(三):CentOS 7.1编译安装Nginx1.9.0》中的configure配置)。

#! /bin/bash
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse
#			   proxy and IMAP/POP3 proxy server
#
# processname: nginx
# config:	  /etc/nginx/nginx.conf
# pidfile:	 /var/run/nginx/nginx.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING>" = "no>" ] && exit 0
nginx="/usr/sbin/nginx>"
prog=$(basename $nginx)
NGINX_CONF_FILE="/etc/nginx/nginx.conf>"
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
lockfile=/var/lock/nginx.lock
start() {
	[ -x $nginx ] || exit 5
	[ -f $NGINX_CONF_FILE ] || exit 6
	echo -n $"Starting $prog: >"
	daemon $nginx -c $NGINX_CONF_FILE
	retval=$?
	echo
	[ $retval -eq 0 ] && touch $lockfile
	return $retval
}
stop() {
	echo -n $"Stopping $prog: >"
	killproc $prog -QUIT
	retval=$?
	echo
	[ $retval -eq 0 ] && rm -f $lockfile
	return $retval
}
restart() {
	configtest || return $?
	stop
	sleep 1
	start
}
reload() {
	configtest || return $?
	echo -n $"Reloading $prog: >"
	killproc $nginx -HUP
	RETVAL=$?
	echo
}
force_reload() {
	restart
}
configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}
rh_status() {
	status $prog
}
rh_status_q() {
	rh_status >/dev/null 2>&1
}
case "$1>" in
	start)
		rh_status_q && exit 0
		$1
		;;
	stop)
		rh_status_q || exit 0
		$1
		;;
	restart|configtest)
		$1
		;;
	reload)
		rh_status_q || exit 7
		$1
		;;
	force-reload)
		force_reload
		;;
	status)
		rh_status
		;;
	condrestart|try-restart)
		rh_status_q || exit 0
			;;
	*)
		echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}>"
		exit 2
esac
 

将上面的shell脚本内容以 Unix格式(不能用dos哦)保存并命名为 nginx,然后上传到centos系统的 /etc/init.d/目录,接着添加可执行权限,最后执行添加到开机启动的命令: chkconfig –add nginxchkconfig nginx on即可。

最后,我们可以使用如下命令对Nginx服务进行操作:

######启动Nginx服务
[[email protected] ~]# service nginx start
######停止Nginx服务
[[email protected] ~]# service nginx stop
######重启Nginx服务
[[email protected] ~]# service nginx restart
######Nginx服务的状态
[[email protected] ~]# service nginx status
######在Nginx服务启动的状态下,重新加载nginx.conf这个配置文件
[[email protected] ~]# service nginx reload
 

原文:http://typecodes.com/web/nginxserviceoptshell.html

Linux Shell 程序调试

Linux Shell程序调试

Shell程序的调试是通过运行程序时加入相关调试选项或在脚本程序中加入相关语句,让shell程序在执行过程中显示出一些可供参考的“调试信息”。当然,用户也可以在shell程序中的适当位置加入一些echo命令用于调试与跟踪。

方法一:在运行脚本程序时加入调试选项:

【用法】bash –选项./shellScript.sh

几个常用的调试选择项如下: 
        -e :如果一个命令返回一个非0退出状态值(失败),就退出。  
        -n : 不需要执行脚本只是检查语法结构,返回所有的语法错误信息。  
        -u : 置换时把未设置的变量看作出错。  
  -v: 当读入shell输入行时,把它们显示出来。  
        -x: 执行命令时,把命令和它们的参数显示出来。  

方法二:在脚本程序中通过
set命令 调试程序:

【用法】set –选项,set +选项      #set命令的常用选项同上

        以在Shell程序内部用“set -选择项”的形式引用,而“set +选择项”则将禁止该选择项起作用。如果只想对程序的某一部分使用某些选择项时,则可以将该部分用上面两个语句包围起来。
 

(1)未置变量退出(-u)和立即退出(-e)

未置变量退出特性允许用户对所有变量进行检查,如果引用了一个未赋值的变量就终止Shell程序的执行。Shell通常允许未置变量的使用,在这种情况下,变量的值为空。如果设置了未置变量退出选择项,则一旦使用了未置变量就显示错误信息,并终止程序的运行。未置变量退出选择项为-u。

当Shell运行时,若遇到不存在或不可执行的命令、重定向失败或命令非正常结束等情况时,如果未经重新定向,该出错信息会显示在终端屏幕上, 而Shell程序仍将继续执行。要想在错误发生时迫使Shell程序立即结束,可以使用-e选项将Shell程序的执行立即终止。

(2)Shell程序的跟踪(-v或-x)

调试Shell程序的主要方法是利用Shell命令解释程序的-v或-x选项来跟踪程序的执行。-v选择项使Shell在执行程序的过程中,把它读入的每一个命令行都显示出来,而-x选择项使Shell在执行程序的过程中把它执行的每一个命令在行首用一个+加上命令名显示出来。并把每一个变量和该变量所取的值也显示出来。因此,它们的主要区别在于:在执行命令行之前无-v,则显示出命令行的原始内容,而有-v时则显示出经过替换后的命令行的内容。

【例子】

./iftest.sh:

#! /bin/bash
iftest(){
	 if  [ $# -ne 1  ]
	then
		echo  " Usage: $0 dir  >"
		exit  1
	fi
   #  set  -v or set  -x	  #若选择方法二,则取消注释,并选择其中一个set命令
	 if  [ -d " $1 >"  ]
	then
		ls  -l $1
		exit  0
	fi
	#  set  +v or set  +x	 #若选择方法二,则取消注释,并选择其中一个set命令
	echo  " Warn:$1 is not a directory! >"
	exit  2
}
iftest ..
 

方法一运行结果:

bash -v ./iftest.sh

bash -x ./iftest.sh

注:$#=1    $1=..  

方法二运行结果:  

取消iftest.sh程序中的注释,并且只选择set -x 和 set +x命令,表明只对第二个if..fi语句块进行调试。

./iftest.sh

感谢:http://www.cnblogs.com/hicome/archive/2007/10/30/943002.html

原文:http://www.cnblogs.com/CherishFX/p/4558958.html

shell: [原]shell终端多目录间快速cd工具

1.解决的问题

当在多个目录间cd的时候,需要输入一大串的路径。例如在不同的项目、不同的分支代码目录跳转,在桌面和文档目录跳转

cd ~/Desktop/project_trunk

cd ~/Download/cang_lao_shi

cd ~/code/branch-1.11/

cd ~/code/branch-3.1/project/android 

这个工具就能令这些cd简化成几个字符:

g2t

g2c

g21

g2a

2.脚本配置

工具是个shell脚本,附在本文末尾,复制整个代码保存为任意文件名,例如g2.sh,然后在 ~/.bashrc的最后一行加入单引号里的内容 ‘source g2.sh’ 或 ‘. g2.sh’

3.自定义路径

如果想加入自定义的路径,找到

shortcut_and_paths=(xxxxx)

的地方,增加一行就可以了。每行就是一个参数和实际命令。可以看到

shortcut_and_paths=(
  'd ~/Desktop'
  's ~/Downloads/subversion-1.7.17'
  '7 ~/Downloads/gmock-1.7.0'
  'n ~/Documents/department/17无线推广部/内部文档/主管文档'
  'wk /home/liuhx/Desktop/WebKit/Source/WTF/icu'
) 

第一个空格前是g2的后缀,第一个空格后是cd的路径。增加完需要重新source或者新建一个terminal才会生效。

如果忘了可以g2啥,可以输入g2help(不是g2hell哦)就能列出所有命令。

附脚本:

#!/bin/bash
#author http://blog.csdn.net/hursing
# this variable should be complex enough to avoid naming pollution
shortcut_and_paths=(
  'd ~/Desktop'
  's ~/Downloads/subversion-1.7.17'
  '7 ~/Downloads/gmock-1.7.0'
  'n ~/Documents/department/17无线推广部/内部文档/主管文档'
  'wk /home/liuhx/Desktop/WebKit/Source/WTF/icu'
)
for ((i = 0; i < ${#shortcut_and_paths&#91;@&#93;}; i++)); do
  cmd=${shortcut_and_paths&#91;$i&#93;}
  shortcut=${cmd%% *}
  path=${cmd#* }
  func="g2$shortcut() { cd $path; }>"
  eval $func
done
g2help() {
  for ((i = 0; i < ${#shortcut_and_paths&#91;@&#93;}; i++)); do
    cmd=${shortcut_and_paths&#91;$i&#93;}
    shortcut=${cmd%% *}
    path=${cmd#* }
    echo -e "g2$shortcutt=>tcd $path>"
  done
  echo -e "33[0;33;1mexample: input 'g2${shortcut_and_paths[0]%% *}' to run 'cd ${shortcut_and_paths[0]#* }'33[0m>"
} 

FAQ:

为什么不用alias呢?因为非交互式shell不会展开alias,也就是用function就能被其它脚本调用了

转载请注明出处: http://blog.csdn.net/hursing

原文:http://blog.csdn.net/hursing/article/details/44098161

shell: [Linux] LNMP环境的搭建

LNMP 是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写:

这篇文章介绍如何在 CentOS 7 (x64) 上搭建 LNMP 环境,当然有些部分可能在其它系统上处理起来有些不同,但是大体上各个 Linux 系统的搭建过程都是类似的

首先是安装一些必要的包,以保证 nginx 的编译及运行顺利

Shell

yum install gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel 

然后到官网下载最新版的 nginx,并且解压进入目录,之后是编译安装,这里我们将其安装到 /usr/local/nginx 目录下

Shell

wget http://nginx.org/download/nginx-1.7.10.tar.gz	# 下载最新版的 nginx
tar zxvf nginx-1.7.10.tar.gz				# 解压
cd nginx-1.7.10
./configure --prefix=/usr/local/nginx
make && make install 

中间如果没有报错的话,那么现在应该已经顺利安装好了,之后进入到刚刚的目录

Shell

cd /usr/local/nginx

尝试运行以下看看有没有问题

Shell

sbin/nginx

如果你看到下面这段文字,就说明有什么东西占用了你的 80 端口,这很有可能是 Apache 的 httpd 程序,它也是一个网页服务器,你可以将它关闭

Shell

nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) 

Shell

systemctl stop httpd
systemctl disable httpd

现在看看 80 端口是否被 nginx 占用了

Shell

# netstat -antlp | grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      6093/nginx: master 

如果是的话,就输入你的地址看看是否能够访问,正常情况下应该是会显示一个欢迎界面之类的东西,但是如果你始终连接不上的话,检查以下防火墙配置,把 80 端口打开

Shell

/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
/sbin/iptables-save > /etc/sysconfig/iptables
systemctl restart iptables 

然后如果要设置开机自动启动,由于我用的是 systemctl,你可以在 /usr/lib/systemd/system 下创建一个叫做 nginx.service 的文件,内容如下。具体目录可以根据实际情况修改

Shell

[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf -g 'pid /run/nginx.pid; error_log stderr;'
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target 

然后运行

Shell

systemctl enable nginx

接下来安装 MySQL 服务,首先到官网 http://dev.mysql.com/downloads/repo/yum/找找相应的数据仓库,然后下载安装

Shell

wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
rpm -ivh mysql-community-release-el7-5.noarch.rpm 

然后安装

Shell

yum install mariadb mariadb-server

接着用 mysql 用户来初始化数据库

Shell

mysql_install_db --user=mysql

然后是启动 mysql 服务

Shell

systemctl start mysqld
systemctl enable mysqld

运行 mysql 命令连接到 mysql 服务

Shell

mysql

如果你看到这些文字,就说明连接成功了

C++

Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 2
Server version: 5.6.23 MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
mysql> 

现在来设置 mysql 的 root 密码

Shell

mysqladmin -u root password  # 这里的 password 不要改动,它会让你输入你的密码 

这样,mysql 服务就算配置完成了,接下来安装 PHP

Shell

yum install php php-fpm php-gd php-mysql php-ldap php-pdo php-snmp php-soap php-mbstrin 

之后运行 php-fpm

Shell

systemctl start php-fpm
systemctl enable php-fpm

然后修改 nginx.conf 的配置

C++

server {
listen	   80;
server_name locahost;
#access_log  logs/host.access.log  main;
location / {
	root   /usr/local/nginx/html;
	# 使得 index.php 成为索引
	index  index.php index.html index.htm;
}
# 添加这些内容
location ~ .php$ {
	root		   html;
	fastcgi_pass   127.0.0.1:9000;
	fastcgi_index  index.php;
	fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name;
	include		fastcgi_params;
}
 

之后在 /usr/local/nginx/html/index.php 写上

PHP

访问网站,就可以看见结果了

原文:http://blog.miskcoo.com/2015/03/linux-lnmp-environment

shell: HBase Shell 常用操作

HBase Shell是HBase的一个命令行工具,我们可以通过它对HBase进行维护操作。我们可以使用sudo -u hbase hbase shell来进入HBase shell。在HBase shell中,可以使用status, version和whoami分别获得当前服务的状态、版本、登录用户和验证方式。

> status
3 servers, 1 dead, 1.3333 average load
> version
0.98.6-cdh5.3.1, rUnknown, Tue Jan 27 16:43:50 PST 2015
> whoami
hbase (auth:SIMPLE)
groups: hbase 

HBase shell中的帮助命令非常强大,使用help获得全部命令的列表,使用help ‘command_name’获得某一个命令的详细信息。例如:

> help 'list'
List all tables in hbase. Optional regular expression parameter could
be used to filter the output. Examples:
  hbase> list
  hbase> list 'abc.*'
  hbase> list 'ns:abc.*'
  hbase> list 'ns:.*' 

1. 命名空间

在HBase系统中,命名空间namespace指的是一个HBase表的逻辑分组,同一个命名空间中的表有类似的用途,也用于配额和权限等设置进行安全管控。

HBase默认定义了两个系统内置的预定义命名空间:

• hbase:系统命名空间,用于包含hbase的内部表

• default:所有未指定命名空间的表都自动进入该命名空间

我们可以通过create_namespace命令来建立命名空间

> create_namespace 'debugo_ns'
0 row(s) in 2.0910 seconds

通过drop_namespace来删除命名空间

> drop_namespace 'debugo_ns'
0 row(s) in 1.9540 seconds

通过alter_namespac改变表的属性,其格式如下:

alter_namespace ‘my_ns’, {METHOD => ‘set’, ‘PROPERTY_NAME’ => ‘PROPERTY_VALUE’}

显示命名空间以及设定的元信息:

> describe_namespace 'debugo_ns'
DESCRIPTION
{NAME => 'debugo_ns'}
1 row(s) in 1.9540 seconds 

显示所有命名空间

> list_namespace
NAMESPACE
debugo_ns
default
hbase
3 row(s) in 0.0910 seconds 

在HBase下建表需要使用create table_name, column_family1, 这个命令:

> create 'user','info'
0 row(s) in 0.9030 seconds
=> Hbase::Table - user 

这个时候这个表是创建在default下面。如果需要在debugo_ns这个命名空间下面建表,则需要使用create namespace:table_name这种方式:

> create_namespace 'debugo_ns'
0 row(s) in 2.0910 seconds
create 'debugo_ns:users', 'info'
0 row(s) in 0.4640 seconds
=> Hbase::Table - debugo_ns:users 

List命令可以列出当前HBase实例中的所有表,支持使用正则表达式来匹配。

> list_namespace_tables 'debugo_ns'
TABLE
users
1 row(s) in 0.0400 seconds 

使用list_namespace_tables也可以直接输出某个命名空间下的所有表

> list_namespace_tables 'debugo_ns'
TABLE
users
1 row(s) in 0.0400 seconds 

2. DDL语句

首先是建立HBase表,上面我们已经用过create命令了。它后面的第一个参数是表名,然后是一系列列簇的列表。每个列簇中可以独立指定它使用的版本数,数据有效保存时间(TTL),是否开启块缓存等信息。

> create 't1', {NAME => 'f1', VERSIONS => 1, TTL => 2592000, BLOCKCACHE => true}, 'f2' 

表也可以在创建时指定它预分割(pre-splitting)的region数和split方法。在表初始建立时,HBase只分配给这个表一个region。这就意味着当我们访问这个表数据时,我们只会访问一个region server,这样就不能充分利用集群资源。HBase提供了一个工具来管理表的region数,即org.apache.hadoop.hbase.util.RegionSplitter和HBase shell中create中的split的配置项。例如:

> create 't2', 'f1', {NUMREGIONS => 3, SPLITALGO => 'HexStringSplit'} 

我们通过describe 来查看这个表中的元信息:

> describe 't2'
DESCRIPTION                                                 ENABLED
 't2', {NAME => 'f1', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'ROW', REPLIC true ATION_SCOPE => '0', VERSIONS => '1', COMPRESSION => 'NONE', MIN_VERSIONS => '0', TTL => 'FOREVER', KEEP_DELETED_CELLS => 'false', BLOCKSIZE => '65536', IN_MEMOR Y => 'false', BLOCKCACHE => 'true'}
1 row(s) in 0.0690 seconds 

通过enable和disable来启用/禁用这个表,相应的可以通过is_enabled和is_disabled来检查表是否被禁用。

> disable 't2'
0 row(s) in 1.4410 seconds
> enable 't2'
0 row(s) in 0.5940 seconds
> is_enabled 't2'
true
0 row(s) in 0.0400 seconds
hbase(main):042:0> is_disabled 't2'
false
0 row(s) in 0.0490 seconds 

使用exists来检查表是否存在

> exists 't2'
Table t2 does exist
0 row(s) in 0.0590 seconds

使用alter来改变表的属性,比如改变列簇的属性, 这涉及将信息更新到所有的region。在过去的版本中,alter操作需要先把table禁用,而在当前版本已经不需要。

> alter 't1', {NAME => 'f1', VERSIONS => 5}
Updating all regions with the new schema...
0/1 regions updated.
1/1 regions updated.
Done.
0 row(s) in 2.3470 seconds 

另外一个非常常用的操作是添加和删除列簇:

> alter 't1','f3'
Updating all regions with the new schema...
0/1 regions updated.
1/1 regions updated.
Done.
0 row(s) in 2.3130 seconds
> alter 't1', 'delete' => 'f3' 

或者:

> alter 't1',{ NAME => 'f3', METHOD => 'delete'}
Updating all regions with the new schema...
0/1 regions updated.
1/1 regions updated.
Done.
0 row(s) in 2.2930 seconds 

删除表需要先将表disable。

> disable 't1'
0 row(s) in 1.4310 seconds
> drop 't1'
0 row(s) in 0.2440 seconds 

3. put与get

在HBase shell中,我们可以通过put命令来插入数据。例如我们新创建一个表,它拥有id、address和info三个列簇,并插入一些数据。列簇下的列不需要提前创建,在需要时通过

:

来指定即可。

> create 'member','id','address','info'
0 row(s) in 0.4570 seconds
=> Hbase::Table – member
put 'member', 'debugo','id','11'
put 'member', 'debugo','info:age','27'
put 'member', 'debugo','info:birthday','1987-04-04'
put 'member', 'debugo','info:industry', 'it'
put 'member', 'debugo','address:city','beijing'
put 'member', 'debugo','address:country','china'
put 'member', 'Sariel', 'id', '21'
put 'member', 'Sariel','info:age', '26'
put 'member', 'Sariel','info:birthday', '1988-05-09	'
put 'member', 'Sariel','info:industry', 'it'
put 'member', 'Sariel','address:city', 'beijing'
put 'member', 'Sariel','address:country', 'china'
put 'member', 'Elvis', 'id', '22'
put 'member', 'Elvis','info:age', '26'
put 'member', 'Elvis','info:birthday', '1988-09-14 '
put 'member', 'Elvis','info:industry', 'it'
put 'member', 'Elvis','address:city', 'beijing'
put 'member', 'Elvis','address:country', 'china' 

获取一个id的所有数据

> get 'member', 'Sariel'
COLUMN                           CELL
 address:city                    timestamp=1425871035382, value=beijing
 address:country                 timestamp=1425871035424, value=china
 id:                             timestamp=1425871035176, value=21
 info:age                        timestamp=1425871035225, value=26
 info:birthday                   timestamp=1425871035296, value=1988-05-09
 info:industry                   timestamp=1425871035334, value=it
6 row(s) in 0.0530 seconds 

获得一个id,一个列簇(一个列)中的所有数据:

> get 'member', 'Sariel', 'info'
COLUMN                           CELL
 info:age                        timestamp=1425871035225, value=26
 info:birthday                   timestamp=1425871035296, value=1988-05-09
 info:industry                   timestamp=1425871035334, value=it
3 row(s) in 0.0320 seconds
> get 'member', 'Sariel', 'info:age'
COLUMN                           CELL
 info:age                        timestamp=1425871035225, value=26
1 row(s) in 0.0270 seconds 

通过describe ‘member’可以看到,默认情况下列簇只保存1个version。我们先将其修改到2,然后update一些信息。

> alter 'member', {NAME=> 'info', VERSIONS => 2}
Updating all regions with the new schema...
0/1 regions updated.
1/1 regions updated.
Done.
0 row(s) in 2.2580 seconds
> put 'member', 'debugo','info:age','29'
> put 'member', 'debugo','info:age','28'
> get 'member', 'debugo', {COLUMN=>'info:age', VERSIONS=>2}
COLUMN                           CELL
 info:age                        timestamp=1425884510241, value=28
 info:age                        timestamp=1425884510195, value=29
2 row(s) in 0.0400 seconds 

4. 其他DML语句

通过delete命令,我们可以删除id为某个值的‘info:age’字段,接下来的get就无视了

> delete 'member','debugo','info:age'
0 row(s) in 0.0420 seconds
> get 'member','debugo','info:age'
COLUMN                           CELL
0 row(s) in 0.3270 seconds 

通过deleteall来删除整行

> delete 'member','debugo','info:age'
0 row(s) in 0.0420 seconds
> get 'member','debugo','info:age'
COLUMN                           CELL
0 row(s) in 0.3270 seconds 

给’Sariel’的’info:age’字段添加,并使用incr实现递增。但需要注意的是,这个value需要是一个数值,如果使用单引号标识的字符串就无法使用incr。在使用Java API开发时,我们可以使用toBytes函数讲数值转换成byte字节。在HBase shell中我们只能通过incr来初始化这个列,

> delete 'member','Sariel','info:age'
0 row(s) in 0.0270 seconds
> incr 'member','Sariel','info:age',26
0 row(s) in 0.0290 seconds
> incr 'member','Sariel','info:age'
0 row(s) in 0.0290 seconds
> incr 'member','Sariel','info:age', -1
0 row(s) in 0.0230 seconds
> get 'member','Sariel','info:age'
COLUMN   CELL
 info:age   timestamp=1425890213341, value=x00x00x00x00x00x00x00x1A
1 row(s) in 0.0280 seconds 

十六进制1A是26,通过上面增1再减1后得到的结果。下面通过count统计行数。

> count 'member'
2 row(s) in 0.0750 seconds
=> 2

通过truncate来截断表。hbase是先将掉disable掉,然后drop掉后重建表来实现truncate的功能的。

hbase(main):010:0> truncate 'member'
Truncating 'member' table (it may take a while):
 - Disabling table...
 - Dropping table...
 - Creating table...
0 row(s) in 2.3260 seconds 

5. scan和filter

通过scan来对全表进行扫描。我们将之前put的数据恢复。

> scan 'member'
ROW                COLUMN+CELL
 Elvis             column=address:city, timestamp=1425891057211, value=
	 beijing
 Elvis             column=address:country, timestamp=1425891057258, val
	 ue=china
 Elvis             column=id:, timestamp=1425891057038, value=22
 Elvis             column=info:age, timestamp=1425891057083, value=26
 Elvis             column=info:birthday, timestamp=1425891057129, value
	 =1988-09-14
 Elvis             column=info:industry, timestamp=1425891057172, value
	 =it
 Sariel            column=address:city, timestamp=1425891056965, value=
	 beijing
 Sariel            column=address:country, timestamp=1425891057003, val
	 ue=china
 Sariel            column=id:, timestamp=1425891056767, value=21
 Sariel            column=info:age, timestamp=1425891056808, value=26
 Sariel            column=info:birthday, timestamp=1425891056883, value
	 =1988-05-09
 Sariel            column=info:industry, timestamp=1425891056924, value
	 =it
 debugo            column=address:city, timestamp=1425891056642, value=
	 beijing
 debugo            column=address:country, timestamp=1425891056726, val
	 ue=china
 debugo            column=id:, timestamp=1425891056419, value=11
 debugo            column=info:age, timestamp=1425891056499, value=27
 debugo            column=info:birthday, timestamp=1425891056547, value
	 =1987-04-04
 debugo            column=info:industry, timestamp=1425891056597, value
	 =it
3 row(s) in 0.0660 seconds3 row(s) in 0.0590 seconds
 

指定扫描其中的某个列:

> scan 'member', {COLUMNS=> 'info:birthday'}

或者整个列簇:

> scan 'member', {COLUMNS=> 'info'}
ROW                              COLUMN+CELL
 Elvis                           column=info:age, timestamp=1425891057083, value=26
 Elvis                           column=info:birthday, timestamp=1425891057129, value=1988-09-14
 Elvis                           column=info:industry, timestamp=1425891057172, value=it
 Sariel                          column=info:age, timestamp=1425891056808, value=26
 Sariel                          column=info:birthday, timestamp=1425891056883, value=1988-05-09
 Sariel                          column=info:industry, timestamp=1425891056924, value=it
 debugo                          column=info:age, timestamp=1425891056499, value=27
 debugo                          column=info:birthday, timestamp=1425891056547, value=1987-04-04
 debugo                          column=info:industry, timestamp=1425891056597, value=it
3 row(s) in 0.0650 seconds 

除了列(COLUMNS)修饰词外,HBase还支持Limit(限制查询结果行数),STARTROW (ROWKEY起始行。会先根据这个key定位到region,再向后扫描)、STOPROW(结束行)、TIMERANGE(限定时间戳范围)、VERSIONS(版本数)、和FILTER(按条件过滤行)等。比如我们从Sariel这个rowkey开始,找下一个行的最新版本:

> scan 'member', { STARTROW => 'Sariel', LIMIT=>1, VERSIONS=>1}
ROW    COLUMN+CELL
 Sariel   column=address:city, timestamp=1425891056965, value=beijing
 Sariel   column=address:country, timestamp=1425891057003, value=china
 Sariel   column=id:, timestamp=1425891056767, value=21
 Sariel   column=info:age, timestamp=1425891056808, value=26
 Sariel   column=info:birthday, timestamp=1425891056883, value=1988-05-09
 Sariel   column=info:industry, timestamp=1425891056924, value=it
1 row(s) in 0.0410 seconds 

Filter是一个非常强大的修饰词,可以设定一系列条件来进行过滤。比如我们要限制某个列的值等于26:

> scan 'member', FILTER=>"ValueFilter(=,'binary:26')>"
ROW    COLUMN+CELL
 Elvis    column=info:age, timestamp=1425891057083, value=26
 Sariel   column=info:age, timestamp=1425891056808, value=26
2 row(s) in 0.0620 seconds 

值包含6这个值:

> scan 'member', FILTER=>"ValueFilter(=,'substring:6')>"
Elvis    column=info:age, timestamp=1425891057083, value=26
 Sariel   column=info:age, timestamp=1425891056808, value=26
2 row(s) in 0.0620 seconds 

列名中的前缀为birthday的:

> scan 'member', FILTER=>"ColumnPrefixFilter('birth') >"
ROW                              COLUMN+CELL
 Elvis                           column=info:birthday, timestamp=1425891057129, value=1988-09-14
 Sariel      column=info:birthday, timestamp=1425891056883, value=1988-05-09
 debugo                          column=info:birthday, timestamp=1425891056547, value=1987-04-04
3 row(s) in 0.0450 seconds 

FILTER中支持多个过滤条件通过括号、AND和OR的条件组合。

> scan 'member', FILTER=>"ColumnPrefixFilter('birth') AND ValueFilter ValueFilter(=,'substring:1987')>"
ROW       COLUMN+CELL
Debugo    column=info:birthday, timestamp=1425891056547, value=1987-04-04
1 row(s) in 0.0450 seconds 

同一个rowkey的同一个column有多个version,根据timestamp来区分。而每一个列簇有多个column。而FIRSTKEYONLY仅取出每个列簇的第一个column的第一个版本。而KEYONLY则是对于每一个column只去取出key,把VALUE的信息丢弃,一般和其他filter结合使用。例如:

> scan 'member', FILTER=>"FirstKeyOnlyFilter()>"
ROW    COLUMN+CELL
 Elvis    column=address:city, timestamp=1425891057211, value=beijing
 Sariel   column=address:city, timestamp=1425891056965, value=beijing
 debugo column=address:city, timestamp=1425891056642, value=beijing
3 row(s) in 0.0230 seconds
> scan 'member', FILTER=>"KeyOnlyFilter()>"
hbase(main):055:0> scan 'member', FILTER=>"KeyOnlyFilter()>"
ROW    COLUMN+CELL
Elvis    column=address:city, timestamp=1425891057211, value=
Elvis    column=id:, timestamp=1425891057038, value=
…… 

PrefixFilter是对Rowkey的前缀进行判断,这是一个非常常用的功能。

> scan 'member', FILTER=>"PrefixFilter('E')>"
ROW    COLUMN+CELL
Elvis    column=address:city, timestamp=1425891057211, value=beijing
……
1 row(s) in 0.0460 seconds 

^^

原文:http://debugo.com/hbase-shell-cmds/

shell: Linux shell批量删除指定目录下的所有目录的编程思路

应用场景:某个目录中存放着许多软件的源码压缩包,在部署完这些软件后,一定会生成许多没用的临时目录,可以通过脚本的方式删除该目录下所有的目录。当这个目录中存在着一些特殊名字的目录时,例如这些目录中有Linux系统所不支持的特殊字符“/”(这些文件通常有可能是Windows系统所支持的)或有目录名中有空格,那批量删除这些目录就会变得困难。

问题分析与解决办法:

问题1.当前工作目录中有一些重要的目录可能不想被删除

解决办法:排除这些目录即可

问题2.需要考虑一些特殊的目录名称,诸如“test dir”,“2015/03/11-log”,“下载”

解决办法:利用inode消除用户命名空间所带来的特殊性

背景知识:

inode是index node或information node的缩写,是一种特殊的结构用于存放文件的基本信息,这些信息包括文件的所有者、类型、访问权限和存放在磁盘中实际数据的位置。inode存放在每一个文件系统的inode表(inode table)中。

Index or Information Node. This is a structure containing the basic information about a file such as owner, type, access permissions and pointers to the actual data on the disk. Inodes are stored in the per filesystem inode table and are referenced through inode numbers. — http://www.linux-tutorial.info/modules.php?name=MContent&obj=glossary&term=inode

如果Linux系统经常与Windows系统中的磁盘或文件进行交互,建议安装mtools,此工具能在不挂载Windows磁盘格式磁盘的情况下,进行读写等操作。

Summary     : Programs for accessing MS-DOS disks without mounting the disks

Description : Mtools is a collection of utilities for accessing MS-DOS files.

: Mtools allow you to read, write and move around MS-DOS filesystem    

: files (normally on MS-DOS floppy disks).  Mtools supports Windows95    

: style long file names, OS/2 XDF disks, and 2m disks    

:    

: Mtools should be installed if you need to use MS-DOS disks

shell实例(核心步骤):

#!/bin/bash
WORK_DIRECTORY_NAME=.
EXCLUDE_DIRECTORY_NAME=python
INODE_OF_EXCLUDE_DIRECTORY_NAME=$(ls -id $EXCLUDE_DIRECTORY_NAME |awk '{print $1}')
INODE_OF_CURRENT_DIRECTORY_NAME=$(ls -Fi $WORK_DIRECTORY_NAME | grep / | awk '{print $1}')
INODE_OF_REMOVE_DIRECTORY_NAME=$(echo $INODE_OF_CURRENT_DIRECTORY_NAME | sed "s/$INODE_OF_EXCLUDE_DIRECTORY_NAME//g>")
for INODE in $INODE_OF_REMOVE_DIRECTORY_NAME; do
    find $WORK_DIRECTORY_NAME -inum $INODE -exec rm -rf {} ;
done 

实际操作结果(仅演示效果不做具体操作):

shell: Linux shell批量删除指定目录下的所有目录的编程思路
shell: Linux shell批量删除指定目录下的所有目录的编程思路

–END–

原文:http://dgd2010.blog.51cto.com/1539422/1619310

shell: CentOS6、7 LVM逻辑卷分区自动扩容Shell脚本编程思路与实例

应用场景和已知存在的问题:

  1. 适用于CentOS6或CentOS7(可能适用于CentOS4或5等早些版本)

  2. 根文件系统(被扩展的文件系统)采用LVM进行管理,例如mount命令输出“/dev/mapper/vg_$hostname-lv_root on / type ext4 (rw)”中含有“mapper”关键词

  3. 自动扩容根文件系统,如果想扩展其他文件系统,例如有的业务应用数据目录不在根分区中,则需要修改Shell脚本代码中的VG_PATH_TO_EXTEND变量(约78行)。

  4. 仅支持ext2、ext3、ext4、xfs等分区格式的文件系统

  5. 可能不支持某些过多自定义的CentOS系统,但核心步骤相似

  6. 脚本中仅添加了scsi磁盘支持,如需要管理其他磁盘,则需要自己扩充脚本

  7. 为了简化脚本,避免执行多次(本程序没有写执行锁),先前已经存在的磁盘名已经设定为sda,见Shell脚本代码中第45行的ONLINE_SCSI_DISK_PRESENT变量

考虑点:

由于CentOS6和CentOS7在默认根文件系统的文件系统格式存在差异,需要判断是否为xfs,如果是xfs则应该使用xfs_growfs而不是一味的使用resize2fs。

使用resize2fs扩展ext2、ext3、ext4格式的文件系统,使用xfs_growfs扩展xfs格式的文件系统

同一脚本在同一系统多次被执行可能引发的错误,可以考虑使用文件锁来解决这个问题

编程思路:

  1. (之前应该准备或检查Shell脚本运行环境)获取当前使用中的块设备文件名

  2. 获取新添加scsi磁盘的文件名

  3. 获取LVM卷组名(vg)、将被扩展的卷组名的文件路径

  4. 将新添加磁盘使用fdisk创建分区并格式化为LVM格式

  5. 创建物理卷,pvcreate

  6. 扩展卷组,vgextend

  7. 调节逻辑卷大小,lvresize

  8. 判断是否是xfs文件系统

  9. 同步文件系统,使得扩容生效

  10. 返回系统磁盘使用情况

Shell代码:

#!/bin/bash
# Usage: Automatic expand lv with LVM managed disk
# 	Setp 1: Add Hard Disk or Storage to Computing unit
#	Setp 2: Execute this script with root privilege
#	Setp 3: Mind info of this script execution result
# Open the refrigerator door, get the shell script execution environment ready
# Put the elephant into the refrigerator, how the shell scripts works
# Close the refrigerator door, check out the result of execution
# Simetimes, we have to pull new elephant or elephant dung out here, unset variables of shell script
function check_execution_result(){
	if [[ ! -z $RETVAL ]]; then
		unset RETVAL
	fi
	RETVAL=$?
	if [[ $RETVAL -ne 0 ]]; then
		echo execution failed!
		exit $RETVAL
	else
		echo execution successfully!
	fi
	unset RETVAL
}
# lsblk --scsi
# lsblk --all
# NAME	    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
# fd0	       2:0    1    4K  0 disk
# sda	       8:0    0   40G  0 disk
# ├─sda1	    8:1    0  500M  0 part /boot
# └─sda2	    8:2    0 39.5G  0 part
#   ├─centos-swap 253:0    0  3.9G  0 lvm  [SWAP]
#   └─centos-root 253:1    0 35.6G  0 lvm  /
# sdb	       8:16   0   16G  0 disk
# sr0	      11:0    1  6.6G  0 rom
# Show present scsi disk online
# Q: Why use "xargs>" here?
# A: Convert the text from multi-line single-column into single-line multi-column, for sed operation
ONLINE_SCSI_DISK_PRESENT=$(lsblk --all | grep disk | grep -v fd | awk '{print $1}' | xargs)
# TODO
# For execution this script beyond twice
ONLINE_SCSI_DISK_PRESENT=sda
# Find new scsi disk online
# TODO figure it out why there is host0?
echo "- - ->" >/sys/class/scsi_host/host0/scan
echo "- - ->" >/sys/class/scsi_host/host1/scan
echo "- - ->" >/sys/class/scsi_host/host2/scan
# Show new added scsi disk online
ONLINE_SCSI_DISK_NEWADD=$(lsblk --all | grep disk | grep -v fd | awk '{print $1}' | xargs echo | sed "s/$ONLINE_SCSI_DISK_PRESENT//g>")
# Construct disk file with full path
echo New Added SCSI Disk: $ONLINE_SCSI_DISK_NEWADD
# Get VG Name
VG_Name=$(vgdisplay | grep 'VG Name' | awk '{print $NF}')
VG_PATH_TO_EXTEND=$(lvdisplay | grep 'LV Path' | awk '{print $NF}' | grep root)
for BLOCK in $ONLINE_SCSI_DISK_NEWADD; do
	ONLINE_SCSI_DISK_NEWADD_FILENAME="/dev/>"$BLOCK
	# end-of-file contents and eof mark must start row1
	fdisk $ONLINE_SCSI_DISK_NEWADD_FILENAME >/dev/null 2>&1<<eof
n
p
1
t
8e
w
eof
	check_execution_result
	LVM_OPERATION_DISK_FILENAME=$ONLINE_SCSI_DISK_NEWADD_FILENAME"1>"
	pvcreate $LVM_OPERATION_DISK_FILENAME >/dev/null 2>&1
	check_execution_result
	vgextend $VG_Name $LVM_OPERATION_DISK_FILENAME >/dev/null 2>&1
	check_execution_result
	lvresize -l +100%FREE $VG_PATH_TO_EXTEND >/dev/null 2>&1
	check_execution_result
# resize2fs - ext2/ext3/ext4 file system resizer
# xfs_growfs, xfs_info - expand an XFS filesystem
#[[email protected] ~]# resize2fs /dev/mapper/centos-root
#resize2fs 1.42.9 (28-Dec-2013)
#resize2fs: Bad magic number in super-block while trying to open /dev/mapper/centos-root
#Couldn't find valid filesystem superblock.
#[[email protected] ~]#
#[[email protected] ~]# xfs_growfs $VG_PATH_TO_EXTEND
#meta-data=/dev/mapper/centos-root isize=256    agcount=4, agsize=2334208 blks
#	 =		       sectsz=512   attr=2, projid32bit=1
#	 =		       crc=0
#data     =		       bsize=4096   blocks=9336832, imaxpct=25
#	 =		       sunit=0      swidth=0 blks
#naming   =version 2	      bsize=4096   ascii-ci=0 ftype=0
#log      =internal	       bsize=4096   blocks=4559, version=2
#	 =		       sectsz=512   sunit=0 blks, lazy-count=1
#realtime =none		   extsz=4096   blocks=0, rtextents=0
#data blocks changed from 9336832 to 13530112
#[[email protected] ~]#
	# Check xfs_info if is installed
	which xfs_info >/dev/null 2>&1
	if [[ $? -ne 0 ]]; then
		yum install xfsprogs -y >/dev/null 2>&1
	fi
	# end Check xfs_info if is installed
	# Check VG_PATH_TO_EXTEND if is xfs filesystem
	xfs_info $VG_PATH_TO_EXTEND >/dev/null 2>&1
	if [[ $? -ne 0 ]]; then
		# is not xfs
		VG_PATH_TO_EXTEND_IS_NOT_XFS=0
	else
		# is xfs
		VG_PATH_TO_EXTEND_IS_NOT_XFS=1
	fi
	# end Check VG_PATH_TO_EXTEND if is xfs filesystem
	# TODO CentOS7 default filesystem is xfs, so we can check it out by OS if is CentOS7
	if [[ $VG_PATH_TO_EXTEND_IS_NOT_XFS ]]; then
		# is xfs
		xfs_growfs $VG_PATH_TO_EXTEND >/dev/null 2>&1
	else
		# is not xfs
		resize2fs $VG_PATH_TO_EXTEND >/dev/null 2>&1
	fi
	check_execution_result
	df -h
	lsblk --all
done
 

测试结果:

(1)添加磁盘前:

(2)添加磁盘并执行脚本后:

shell: CentOS6、7 LVM逻辑卷分区自动扩容Shell脚本编程思路与实例
shell: CentOS6、7 LVM逻辑卷分区自动扩容Shell脚本编程思路与实例

由此可见根分区已经由原先的36GB变为52GB,表示LVM扩容成功。

–END–

原文:http://dgd2010.blog.51cto.com/1539422/1619692

shell: shell脚本生成xml文件

今天把这段时间学习完shell后完成工作上的一个小案件整理了一下,分享给大家!

说来也巧了,作为一个刚刚毕业半年的菜鸟,进入公司后,听公司的大牛推荐学习linux–”鸟哥的私房菜“,基本上是从去年8月份开始到了今年的1月份,基本上是把基础篇看完了,开始了解shell脚本的相关知识。刚好公司有了一个shell脚本的案件给我了,时间上也没有多紧。然后就一边学习一边开始做,虽然中途客户反映先前的业务逻辑有问题耽搁了两周,但总算是到最后完成了,自己学习的东西能用到很开心,今天闲了,把代码整理了一下,分享给大家

具体是这样:

要求是写一个shell脚本,安装要求查询数据,将符合条件的数据按照客户给定的xml样式进行组装,然后加入到crontab中,定时执行通过scp或者ftp放到客户服务器上。

具体实现步骤:

一、编写生成xml文档的代码

网上搜索了一篇博客:http://blog.csdn.net/dengzhaoqun/article/details/7262271   拿来学习了一下,感觉好用,自己就根据自己的实际情况修改了一下:

1 #! /bin/bash
2 # filename: create_xml.sh
3 # create_wangxb_20150123
4 #
5 # 从外部传入的第一个参数作为xml的文件名
6 outfile=$1
7 # xml中的缩进位
8 tabs=0
9
10 # ++++++++++++++++++++++++++++
11 # 组装一个节点,输出到文件
12 # 说一说传参数时的这几个区别:假如有下面这个脚本执行的命令
13 # /path/to/scriptname opt1 opt2 opt3 opt4
14 # $0 : 的值是默认是脚本的名字,从$1 -$4 开始就是参数的值
15 # $# :代表后接的参数『个数』
16 # [email protected] :代表『 " $1 >" " $2 >" " $3 >" " $4 >" 』之意,每个变量是独立的(用双引号括起来);
17 # $* :代表『 " $1c$2c$3c$4 >" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 " $1 $2 $3 $4 >" 』之意。
18 # 在shell中我们可以也可以使用${}包含变量名,来调用变量
19 # ++++++++++++++++++++++++++++
20 put(){
21 echo ' < ' ${*}' > ' >> $outfile
22 }
23
24 # 这里也是输出一个xml的节点,只是比上面的节点有更多的设置
25 # ${@:2 } 的意思:它的值就是由第二个参数开始到最后一个参数,为什么要这样?有时可能你的第二个参数中有空格,shell接受参数是以空格计算的
26 put_tag() {
27 echo ' < ' $1 ' > ' ${@:2 }' </ ' $1 ' > ' >> $outfile
28 }
29 # 同样是一个输出节点函数,但是添加了CDATA,防止特殊字符造成xml解析失败
30 put_tag_cdata() {
31 echo ' < ' $1 ' ><![CDATA[ ' ${@:2 }' ]]></ ' $1 ' > ' >> $outfile
32 }
33
34 put_head(){
35 put ' ? ' ${1 }' ? '
36 }
37 # 这是一个缩进的算法,自行理解
38 out_tabs(){
39 tmp=0
40 tabsstr=">"
41 while [ $tmp -lt $((tabs)) ]
42 do
43 tabsstr=${tabsstr}' t '
44 tmp=$((tmp+1 ))
45 done
46 echo -e -n $tabsstr >> $outfile
47 }
48
49 tag_start(){
50 out_tabs
51 put $1
52 tabs=$((tabs+1 ))
53 }
54
55 tag() {
56 out_tabs
57 if [ " $1 >" == 0 ]
58 then
59 put_tag $2 $(echo ${@:3 })
60 elif [ " $1 >" == 1 ]
61 then
62 put_tag_cdata $2 $(echo ${@:3 })
63 fi
64 }
65
66 tag_end(){
67 tabs=$((tabs-1 ))
68 out_tabs
69 put ' / ' ${1 }
70 }

这里有一些基础知识:

关于参数:

假如有下面这个脚本执行的命令

/path/to/scriptname opt1 opt2 opt3 opt4

1 $0 : 的值是默认是脚本的名字,从$1 -$4 开始就是参数的值
2 $# :代表后接的参数『个数』
3 [email protected] :代表『 ” $1 >” ” $2 >” ” $3 >” ” $4 >” 』之意,每个变量是独立的(用双引号括起来);
4 $* :代表『 ” $1c$2c$3c$4 >” 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 ” $1 $2 $3 $4 >” 』之意。
5 在shell中我们可以也可以使用${}包含变量名,来调用变量 [/code]

关于 ${@:2} 这种形式的说明,我转载了一篇博客:http://www.cnblogs.com/wxb0328/p/4276751.html

二、从数据库查数据利用上面的函数,制作xml文件

1 #!/bin/bash
2 # filename: ts_xml.sh
3 # create_wangxb_20150126
4 #
5
6 PATH=/u01/app/oracle/product/10.2 .0 /db_1/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/opt/dell/srvadmin/bin:/home/p3s_batch/tools:/home/p3s_batch/bin
7 export PATH
8 # Database account information file
9 source ~/.p3src
10
11 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 # set some variable
13 # XMLSCRIPT: 脚本的绝对路径
14 # MATCHING_RESULT_XML: xml_1的文件名
15 # XML_FUNC_FILE: 生成xml函数文件路径
16 # MATCHING_RESULT_QUERY_DATA: sqlplus 查出数据保存的零时文件
17 # MATCHING_RESULT_QUERY_SQL: sqlplus 查询的sql语句
18 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19 # 下面是一些基础的设置
20 export XMLSCRIPT=/usr/p3s/batch/jaaa_match/tmp_xa_wangxb
21 XML_DIR=” $XMLSCRIPT/xmldata >”
22 XML_FUNC_FILE=” xml_func.sh >”
23
24 MATCHING_RESULT_XML=” matching_result_ >” $(date ‘ +%Y%m%d_%H%M%S ‘ )” .xml >”
25 MATCHING_RESULT_QUERY_DATA=” matching_result_query_data.tmp >”
26 MATCHING_RESULT_QUERY_SQL=” matching_result_query.sql >”
27
28 CLIENT_LIST_XML=” client_list_ >” $(date ‘ +%Y%m%d_%H%M%S ‘ )” .xml >”
29 CLIENT_LIST_QUERY_DATA=” client_list_query_data.tmp >”
30 CLIENT_LIST_QUERY_SQL=” client_list_query.sql >”
31
32 # add_wangxb_20150225
33 if [ ! -d ” $XML_DIR >” ];
34 then
35 mkdir $XML_DIR
36 fi
37
38 #+++++++++++++++++++++++++++
39 # modify_wangxb_20150224
40 # check for temporary file
41 #+++++++++++++++++++++++++++
42 if [ -e ” $XML_DIR/$MATCHING_RESULT_XML >” ];
43 then
44 rm -f $XML_DIR/$MATCHING_RESULT_XML
45 fi
46
47 if [ -e ” $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA >” ];
48 then
49 MATCHING_RESULT_QUERY_DATA=” matching_result_query_data_ >” $(date ‘ +%Y%m%d%H%M%S ‘ )” .tmp >”
50 fi
51 #+++++++++++++++++++++++++++++++++++++++++++++++++
52 # add_wangxb_20150225
53 # check system time , choice query time period
54 # 这是是根据crontab每天执行的时间,取得我们查询数据库时的where条件的时间区间
55 #+++++++++++++++++++++++++++++++++++++++++++++++++
56 sys_datetime=$(date ‘ +%Y%m%d%H ‘ )
57 first_chk_datetime=” $(date ‘+%Y%m%d’)04 >”
58 second_chk_datetime=” $(date ‘+%Y%m%d’)12 >”
59 third_chk_datetime=” $(date ‘+%Y%m%d’)20 >”
60 # 由于服务器crontab是上面的时间,但是执行的shell比较多,在调用我这个shell的时候,不一定就是04:30 ,12 :30 , 20 :30所以,这里的根据系统的时间判断时 范围给的比较宽
61 case $sys_datetime in
62 ” $first_chk_datetime >” |” $(date ‘+%Y%m%d’)05 >” |” $(date ‘+%Y%m%d’)06 >” |” $(date ‘+%Y%m%d’)07 >” )
63 chk_start=$(date ‘ +%Y-%m-%d 21:00:00 ‘ -d ‘ -1 day ‘ )
64 chk_end=$(date ‘ +%Y-%m-%d 04:29:59 ‘ )
65 ;;
66 ” $second_chk_datetime >” |” $(date ‘+%Y%m%d’)13 >” |” $(date ‘+%Y%m%d’)14 >” |” $(date ‘+%Y%m%d’)15 >” )
67 chk_start=$(date ‘ +%Y-%m-%d 04:30:00 ‘ )
68 chk_end=$(date ‘ +%Y-%m-%d 12:29:59 ‘ )
69
70 ;;
71 ” $third_chk_datetime >” |” $(date ‘+%Y%m%d’)21 >” |” $(date ‘+%Y%m%d’)22 >” |” $(date ‘+%Y%m%d’)23 >” )
72 chk_start=$(date ‘ +%Y-%m-%d 12:30:00 ‘ )
73 chk_end=$(date ‘ +%Y-%m-%d 20:59:59 ‘ )
74
75 ;;
76 *)
77 chk_start=$(date ‘ +%Y-%m-%d 00:00:00 ‘ )
78 chk_end=$(date ‘ +%Y-%m-%d 23:59:59 ‘ )
79
80 ;;
81 esac
82
83 # modify_wangxb_20150310
84 # 下面的是做一个oracle数据库连接的测试,如果连接失败,后续代码不再执行,并且写入错误日志
85 $ORACLE_HOME/bin/sqlplus -s $ORAUSER_WEB_PASDB << EOF 86 set echo off 87 set feedback off 88 alter session set nls_date_format=’ YYYY-MM-DD:HH24:MI:SS ‘ ; 89 select sysdate from dual; 90 quit 91 EOF 92 if [ $? -ne 0 ] 93 then 94 echo ” ********** DBへのリンク己窃した ********** >”
95 exit
96 else
97 echo ” ********** DBへのリンクOKです ********** >”
98 fi
99 # sqlplus就是oracle的一个客户端软件,具体使用方法可以问度娘,这里传入要执行的sql和参数,将结果 > 输出到指定文件
100 $ORACLE_HOME/bin/sqlplus -s $ORAUSER_WEB_PASDB @$XMLSCRIPT/$MATCHING_RESULT_QUERY_SQL ” $chk_start >” ” $chk_end >” > $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA
101
102
103 # create matching result’ s xml file
104 # add_wangxb_20150227
105 # 下面的算法就是将查出的数据进行分析,调用xml函数生成xml文件
106 source ” $XMLSCRIPT/$XML_FUNC_FILE >” ” $XML_DIR/$MATCHING_RESULT_XML >”
107 put_head ‘ xml version=”1.0>” encoding=”utf-8>” ‘
108 tag_start ‘ ROOT ‘
109 if [ -s ” $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA >” ];
110 then
111 datas=${XMLSCRIPT}/${MATCHING_RESULT_QUERY_DATA}
112 #for res in $datas
113 while read res;
114 do
115 stock_id=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $1} ‘ )
116 seirino=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $2} ‘ )
117 match_flg=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $3} ‘ )
118 unmatch_riyuu=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $4} ‘ )
119 up_date_tmp=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $5} ‘ )
120 up_date=$(echo $up_date_tmp | awk ‘ BEGIN {FS=”@>”} {print $1 ” >” $2} ‘ )
121 tag_start ‘ MATCHING ‘
122 tag 0 ‘ STOCKID ‘ ${stock_id:-“>” }
123 tag 0 ‘ SEIRINO ‘ ${seirino:-“>” }
124 tag 0 ‘ RESULT ‘ ${match_flg:-“>” }
125 tag 1 ‘ REASON ‘ ${unmatch_riyuu:-“>” }
126 tag 0 ‘ UPDATE_DATE ‘ ${up_date:-“>” }
127 tag_end ‘ MATCHING ‘
128 done < $datas 129 fi 130 tag_end ‘ ROOT ‘ 131 rm $XMLSCRIPT/$MATCHING_RESULT_QUERY_DATA 132 133 134 # create client list’ s xml file 135 # add_wangxb_2015027 136 # 下面的是再生成一个xml文件,和上面一样 137 if [ -e ” $XML_DIR/$CLIENT_LIST_XML >” ];
138 then
139 rm -f $XML_DIR/$CLIENT_LIST_XML
140 fi
141
142 if [ -e ” $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA >” ];
143 then
144 CLIENT_LIST_QUERY_DATA=” client_list_query_data_ >” $(date ‘ +%Y%m%d%H%M%S ‘ )” .tmp >”
145 fi
146
147
148 $ORACLE_HOME/bin/sqlplus -s $ORAUSER_MND @$XMLSCRIPT/$CLIENT_LIST_QUERY_SQL > $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA
149
150 source ” $XMLSCRIPT/$XML_FUNC_FILE >” ” $XML_DIR/$CLIENT_LIST_XML >”
151 put_head ‘ xml version=”1.0>” encoding=”utf-8>” ‘
152 tag_start ‘ ROOT ‘
153 if [ -s ” $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA >” ];
154 then
155 datas=${XMLSCRIPT}/${CLIENT_LIST_QUERY_DATA}
156 #for res in $datas
157 while read res;
158 do
159 corporation_id=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $1} ‘ )
160 corporation_name=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $2} ‘ )
161 client_id=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $3} ‘ )
162 client_print_name=$(echo $res | awk ‘ BEGIN {FS=”\^\*\^>”} {print $4} ‘ )
163 tag_start ‘ CLIENT ‘
164 tag 0 ‘ CORPORATION_ID ‘ ${corporation_id:-“>” }
165 tag 1 ‘ CORPORATION_NAME ‘ ${corporation_name:-“>” }
166 tag 0 ‘ CLIENT_ID ‘ ${client_id:-“>” }
167 tag 1 ‘ CLIENT_PRINT_NAME ‘ ${client_print_name:-“>” }
168 tag_end ‘ CLIENT ‘
169 done < $datas 170 fi 171 tag_end ‘ ROOT ‘ 172 rm $XMLSCRIPT/$CLIENT_LIST_QUERY_DATA 173 174 175 # add_wangxb_20150304 176 # Convert xml file encoding 177 # 这是将xml文件进行转码,命令是iconv 178 if [ -e ” $XML_DIR/$MATCHING_RESULT_XML >” ];
179 then
180 echo ” ********** matching_result.xmlファイルコ〖ドを啪垂し、********** >”
181 iconv -f euc-jp -t utf-8 $XML_DIR/$MATCHING_RESULT_XML -o $XML_DIR/$MATCHING_RESULT_XML.utf-8
182 mv $XML_DIR/$MATCHING_RESULT_XML.utf-8 $XML_DIR/$MATCHING_RESULT_XML
183 fi
184 if [ -e ” $XML_DIR/$CLIENT_LIST_XML >” ];
185 then
186 echo ” ********** client_list.xmlフィルコ〖ドを啪垂し、********** >”
187 iconv -f euc-jp -t utf-8 $XML_DIR/$CLIENT_LIST_XML -o $XML_DIR/$CLIENT_LIST_XML.utf-8
188 mv $XML_DIR/$CLIENT_LIST_XML.utf-8 $XML_DIR/$CLIENT_LIST_XML
189 fi
190
191 # add_wangxb_20150304
192 # Send the xml file to the destination server by ftp
193 #ftp_host=” 222.***.***.*** >”
194 #USER=” *** >”
195 #PASS=” *** >”
196 #ftp -i -n $ftp_host << EOF 197 #user $USER $PASS 198 #cd / 199 #lcd $XML_DIR/ 200 #put $MATCHING_RESULT_XML 201 #put $CLIENT_LIST_XML 202 #quit 203 #EOF 204 205 # test ftp 206 # 通过ftp将xml文件放到客户服务器上,ftp_host:客户服务器地址,user登录名,pass密码 207 ftp_host=” ***.***.***.*** >”
208 USER=” *** >”
209 PASS=” *** >”
210 dir =” /upload >”
211 ftp -i -n $ftp_host << EOF 212 user $USER $PASS 213 cd /upload/ 214 lcd $XML_DIR/ 215 put $MATCHING_RESULT_XML 216 put $CLIENT_LIST_XML 217 quit 218 EOF 219 220 221 # Save the program log file 222 YYMM=$(date +’ %Y%m%d%H%M ‘ ) 223 cp /tmp/create_xml.log /usr/p3s/batch/jaaa_match/tmp_xa_wangxb/logs/create_xml.log.$YYMM 224 225 # Send error log files into the Admin mailbox 226 info_to_mail_1=” **@**.co.jp >”
227 info_to_mail_2=” ***@**.co.jp >”
228 # nkf 日文转码的一个命令
229 title=$(echo ” test >” | nkf -j)
230 nkf -j < /tmp/create_xml.log | mail -s $title $info_to_mail_1 $info_to_mail_2
231
232
233 #exit[/code]

关于nkf 日文转码 :http://www.cnblogs.com/wxb0328/p/4333820.html

本来是用scp传送的, 但是后面修改了,这里把自己为scp传送找到的一个,不用密码可立即登入的 ssh 用户

在鸟哥私房菜的服务器架设篇的第十一章中有介绍:http://vbird.dic.ksu.edu.tw/linux_server/0310telnetssh_2.php#ssh_nopasswd

下面是执行的两个sql文件

1 SET PAGESIZE 0
2 SET FEEDBACK OFF
3 SET VERIFY OFF
4 SET ECHO OFF
5 SET HEADING OFF
6 SET TIMI OFF
7 SET LINESIZE 1000
8 SET WRAP OFF
9
10
11 SELECT s.STOCKID|| ‘ ^*^ ‘ || a.SERI_NO|| ‘ ^*^ ‘ || a.MATCH_FLG|| ‘ ^*^ ‘ || a.UNMATCH_RIYUU|| ‘ ^*^ ‘ || to_char(a.UP_DATE,’ [email protected]:MI:SS ‘ ) UP_DATE FROM aaa_stock_db a LEFT JOIN SENDDATAAPPRAISALPROTO s ON a.SERI_NO= s.SEIRINO WHERE a.UP_DATE BETWEEN to_date(‘ &1 ‘ ,’ yyyy-mm-dd hh24:mi:ss ‘ ) AND to_date(‘ &2 ‘ ,’ yyyy-mm-dd hh24:mi:ss ‘ ) AND a.DEL_FLG= 0 ORDER BY a.UP_DATE DESC ;
12
13 exit [/code]

1 SET PAGESIZE 0
2 SET FEEDBACK OFF
3 SET VERIFY OFF
4 SET ECHO OFF
5 SET HEADING OFF
6 SET TIMI OFF
7 SET LINESIZE 1000
8 SET WRAP OFF
9
10
11 SELECT a.CORPORATION_ID|| ‘ ^*^ ‘ || a.CORPORATION_NAME|| ‘ ^*^ ‘ || b.CLIENT_ID|| ‘ ^*^ ‘ || (select CLIENT_PRINT_NAME from CLIENT_MASTER where CLIENT_ID = b.CLIENT_ID) as CLIENT_PRINT_NAME FROM M_CORPORATION_MASTER a LEFT JOIN M_CORPORATION_GROUP b ON (a.CORPORATION_ID = b.CORPORATION_ID) WHERE a.DEL_FLG= 0 AND b.DEL_FLG= 0 ;
12
13 exit [/code]

三、来看看效果

当然中间出现了许多bug,不过慢慢修改吗,兵来将挡,水来土掩,bug来了自己调么

shell: shell脚本生成xml文件
shell: shell脚本生成xml文件

就这样简单的整理一下,可能光这么写不够完整,但是,中间设计的知识也很多,不能展开了说,做个分享,大家有用到的时候也是个思路,具体的某些知识点可以用到了再去找资料了

题外话:

这几天打算辞职,想去外面,但是听了在外面找工作的同学说,外面要求的技术很多:“什么优化,缓存,环境搭建啊,高并发,读写分离,负载均衡等等”  。突然就没有了去外面的激情,而且毕竟才毕业半年,工资也不高,毕业前出去旅行也借了5K的钱都没有还,哎、、、本来想着去深圳,怎么也能找个6K+的工作,现在听听,觉得能力不够啊,这是这些能力也不是一天两天能掌握的,很郁闷,如果不出去,要等到什么时候,趁年轻不出去怕以后就没有机会!

哎、、、这个决定该怎么做,有点烦!如果哪位大牛能够看到小弟这篇博客,希望能提点建设性的意见,不胜感激!!涕泗横流!!!

原文:http://www.cnblogs.com/wxb0328/p/shellxml.html

shell: 提高Linux工作效率的十大bash技巧

来自: 程序师

链接:http://www.techug.com/ten-tips-for-wonderful-bash-productivity

我喜欢钻研bash环境。很多时候,在使用bash编程中,有些问题一遍又一遍的重复遇到。每次我都需要重新思考这些问题的解决方法。直到有一天我无法忍受,于是坐下来,编写一个通用的函数,放入我的.bashrc文件中,部署到电脑上。

希望我的这些追求最大化命令行效率的努力成果也能给其他喜欢使用bash的朋友们带来一些帮助。我更大的期望是我的这种行为能引起其他朋友的互动——给我提建议、提出更好的bash技巧,请在文后留言讨论,或在 @程序师视野 给我留言。

别的不多说了,下面就是我的总结。

技巧一、用命令行往文件的顶部添加文字

每次我都会重新寻找这个命令的写法。下面就是如何使用sed往一个文件顶部添加一行的方法:

sed -i '1s/^/line to insertn/' path/to/file/you/want/to/change.txt

技巧二、用命令行往配置文件里插入多行文本

这种方法非常简单,很多人都知道,下面就是如何用命令行将(>>)多行文本插入一个文件中。这里使用的是“here document”语法,它能让你通过块文本符号来将段落插入文件中,通常用的符合是EOF(意思是 “End Of File”):

cat >> path/to/file/to/append-to.txt << "EOF>“

export PATH=$HOME/jdk1.8.0_31/bin:$PATH

export JAVA_HOME=$HOME/jdk1.8.0_31/

EOF

两个”EOF“之间的所有内容都会被添加到文件中。

技巧三、用命令行递归方式全局搜索目录文件和替换

如果你使用Eclipse,ItelliJ或其它IDE,这些工具的强大重构能力也许会让你轻松实现很多事情。但我估计很多时候你的开发环境中没有这样的集成工具。

如何使用命令行对一个目录进行递归搜索和替换?别想Perl语言,你可以使用find and sed。感谢Stack Overflow提供的指导:

# OSX version

find . -type f -name ‘*.txt’ -exec sed -i ” s/this/that/g {} +

使用了一段时间后,我总结写出了一个函数,添加入了 .bashrc ,就像下面这样:

function sr {

find . -type f -exec sed -i ” s/$1/$2/g {} +

}

你可以像这样使用它:

sr wrong_word correct_word

技巧四、用命令行在vim和Dropbox里开启一个临时文件

我过去喜欢用Emacs里的scratch facility功能。也经常用Vim快速创建临时文件。下面这两个函数是使用openssl生成随机的字符串作为文件名:

function sc {

gvim ~/Dropbox/$(openssl rand -base64 10 | tr -dc ‘a-zA-Z’).txt

}

function scratch {

gvim ~/Dropbox/$(openssl rand -base64 10 | tr -dc ‘a-zA-Z’).txt

}

在命令行窗口输入sc或scratch,一个新的gvim或macvim窗口就会弹出来,里面会加载一个随机文件名的临时文件。

技巧五、用命令行下载文件,包括链接转向、HTTPS和安全加密等情况。

下载一个页面输出到终端,跟随链接转向,忽略安全异常:

curl -Lks 

下载一个链接,跟随链接转向,忽略安全异常:

curl -OLks 

这里用了很多参数,你可以阅读这个简单的curl文档来了解它们。

技巧六、Bashmarks

你还没有在.bashrc里使用bashmarks吗?还在等待什么?它真的非常有用。它能帮你保持历史操作,跳回到你经常使用的目录。下面是我的配置文件里脚本,但我想上面的链接能提供你更多技巧:

# USAGE:

# s bookmarkname – saves the curr dir as bookmarkname

# g bookmarkname – jumps to the that bookmark

# g b[TAB] – tab completion is available

# l – list all bookmarks

# save current directory to bookmarks

touch ~/.sdirs

function s {

cat ~/.sdirs | grep -v “export DIR_$1=>” > ~/.sdirs1

mv ~/.sdirs1 ~/.sdirs

echo “export DIR_$1=$PWD>” >> ~/.sdirs

}

# jump to bookmark

function g {

source ~/.sdirs

cd $(eval $(echo echo $(echo $DIR_$1)))

}

# list bookmarks with dirnam

function l {

source ~/.sdirs

env | grep “^DIR_>” | cut -c5- | grep “^.*=>”

}

# list bookmarks without dirname

function _l {

source ~/.sdirs

env | grep “^DIR_>” | cut -c5- | grep “^.*=>” | cut -f1 -d “=>”

}

# completion command for g

function _gcomp {

local curw

COMPREPLY=()

curw=${COMP_WORDS[COMP_CWORD]}

COMPREPLY=($(compgen -W ‘`_l`’ — $curw))

return 0

}

# bind completion command for g to _gcomp

complete -F _gcomp g

技巧七、从格式化输出里提取一列(我最常使用的awk技巧)

我几乎天天都会使用它。真的。经常会有一些输出,我只需要其中的第二列,或第三列,下面这个命令就能做到这些:

#Sample output of git status -s command:

$ git status -s

M .bashrc

?? .vim/bundle/extempore/

# Remove status code from git status and just get the file names

$ git status -s | awk ‘{print $2}’

.bashrc

.vim/bundle/extempore/

为什么不写个函数,让我们随时都可以用呢?

function col {

awk -v col=$1 ‘{print $col}’

}

这使得提取列非常容易,比如,你不想要第一列?简单:

$ git status -s | col 2

.bashrc

.vim/bundle/extempore/

技巧八、忽略头x个词

我对xargs很着迷,我感觉它就像一把快刀。但有时候用它获得的结果需要调整一下,也许需要取得一些值。例如,你想去掉下面文件影像里的一些信息:

function skip {

n=$(($1 + 1))

cut -d’ ‘ -f$n-

}

下面是如何使用它:

●使用 docker images 得到下面的输出:

$ docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

65a9e3ef7171 3 weeks ago 1.592 GB

7c01ca6c30f2 3 weeks ago 11.1 MB

9518620e6a0e 3 weeks ago 7.426 MB

430707ee7fe8 3 weeks ago 7.426 MB

boot2docker/boot2docker latest 1dbd7ebffe31 3 weeks ago 1.592 GB

spaceghost/tinycore-x86_64 5.4 f47686df00df 7 weeks ago 11.1 MB

durdn/bithub latest df1e39df8dbf 8 weeks ago 100.9 MB

c5e6cf38d985 8 weeks ago 100.9 MB

nginx latest e426f6ef897e 12 weeks ago 100.2 MB

zoobab/tinycore-x64 latest 8cdd417ec611 8 months ago 7.426 MB

scratch latest 511136ea3c5a 20 months ago 0 B

●使用上面的函数,你可以获取所有的IDs:

$ docker images | col 3

IMAGE

65a9e3ef7171

7c01ca6c30f2

9518620e6a0e

430707ee7fe8

1dbd7ebffe31

f47686df00df

df1e39df8dbf

c5e6cf38d985

e426f6ef897e

8cdd417ec611

511136ea3c5a

● 进一步处理:

docker images | col 3 | xargs

IMAGE 65a9e3ef7171 7c01ca6c30f2 9518620e6a0e 430707ee7fe8 1dbd7ebffe31 f47686df00df df1e39df8dbf c5e6cf38d985 e426f6ef897e 8cdd417ec611 511136ea3c5a

●但前面的”IMAGE”字符我也想去掉:

docker images | col 3 | xargs | skip 1

65a9e3ef7171 7c01ca6c30f2 9518620e6a0e 430707ee7fe8 1dbd7ebffe31 f47686df00df df1e39df8dbf c5e6cf38d985 e426f6ef897e 8cdd417ec611 511136ea3c5a

●完整的写下来就是这样:

docker rmi $(docker images | col 3 | xargs | skip 1)

技巧九、创建自己的命令包

在bash里,你可以很容易的创建自己的命令组件,你可以看一下下面我写的:

function dur {

case $1 in

clone|cl)

git clone [email protected]:nicolapaolucci/$2.git

;;

move|mv)

git remote add bitbucket [email protected]:nicolapaolucci/$(basename $(pwd)).git

git push –all bitbucket

;;

trackall|tr)

#track all remote branches of a project

for remote in $(git branch -r | grep -v master ); do git checkout –track $remote ; done

;;

key|k)

#track all remote branches of a project

ssh $2 ‘mkdir -p .ssh && cat >> .ssh/authorized_keys’ < ~/.ssh/id_rsa.pub

;;

fun|f)

#list all custom bash functions defined

typeset -F | col 3 | grep -v _ | xargs | fold -sw 60

;;

def|d)

#show definition of function $1

typeset -f $2

;;

help|h|*)

echo “[dur]dn shell automation tools>”

echo “commands available:>”

echo ” [cl]one, [mv|move]>”

echo ” [f]fun lists all bash functions defined in .bashrc>”

echo ” [def] lists definition of function defined in .bashrc>”

echo ” [k]ey copies ssh key to target host>”

echo ” [tr]ackall], [h]elp>”

;;

esac

}

通过上面的脚本,我可以将ssh key拷贝到任何网站服务器——只需要键入 dur key

[email protected]

总结

你可以试一下我的这个.bashrc文件,或你自己也可以写一个。你有更好更多的技巧吗?请写在下面的评论里,或私信给 @程序师视野 。期待你的来信。

来自: 程序师

链接:http://www.techug.com/ten-tips-for-wonderful-bash-productivity

—————————————————

●本文编号732,以后想阅读这篇文章直接输入732即可。

●本文分类“ Linux ”,搜索分类名可以获得相关文章。

●输入m可以获取到全部文章目录

●输入r可以获取到热门文章推荐

●输入f可以获取到全部分类名称

—————————————————

推荐公众微信「 IT电商网 」报道热点电商资讯,分享有价值的电商营销案例。电商创业、电商从业者必须关注的公众微信,绝对都是精选文章!微信号: itdianshang

(长按上图↑可自动识别二维码)

点击“阅读原文”也可关注

↓↓↓

原文:http://mp.weixin.qq.com/s?__biz=MjM5NzA1MTcyMA==&mid=204873961&idx=4&sn=43c8b5bc924a93fce8053749e8aecf0c&3rd=MzA3MDU4NTYzMw==&scene=6#rd

shell: Bash内部变量

Bash内部变量

有些内部命令在目录列表时是看不见的,他们有Shell本身提供,常见的内部命令:echo,eval,execexport,readonly,read,shift ,wait,exit和点(.)

echo 变量名表

将变量名表指定的变量显示到标准输出

Evalargs

读入参数args ,并将他们组合成一个新的命令,然后执行

Exec命令参数

当Shell执行到exec语句时,不会去创建新的子进程,而是转去执行新的命令,当指定的命令执行完时,该进程(也就是当初的Shell)就终止了,所以Shell程序中的exec后面的语句将不再被执行

Export 变量名=value

Shell 可以用export把它的变量向下打入子Shell,从而让子进程继承父进程中的环境变量,但子Shell不能用export把他的变量向上带入父Shell

Readonly 变量名

从边准输入读字符床,传给指定变量

Shift 语句

Shift 语句按如下方式重新命名所有的位置参数变量,即 $2成为$1,$3成为$2…在程序中每使用一次shift语句,都使得所有的位置一次向左移动一个位置,并使位置参数$#减1,直到减到0为止。

ssh-copy-id  –I  pub

Vi /usr/bin/ssh-copy-id

举例:

if [ “-i>” = “$1>” ];then

shift

#check if we have 2 parameters left, if so the first is the new ID file

if[ -n “$2>” ]; then

if expr “$1>” : “.*.pub>” ; then

ID_FILE=”$1>”

else

ID_FILE=”$1.pub>”

fi

shift        # and this shouldleave $1 as the target name

fi

else

if[ x$SSH_AUTH_SOCK != x ] ; then

GET_ID=”$GET_ID ssh-add -L>”

Linux Bash脚本编程语言中的美学与哲学 http://www.linuxidc.com/Linux/2015-03/114436.htm

提高Linux工作效率的十大bash技巧 http://www.linuxidc.com/Linux/2015-03/114349.htm

bash的登录与欢迎信息:/etc/issue,/etc/motd http://www.linuxidc.com/Linux/2014-08/105419.htm

Bash常用的几个配置文件 http://www.linuxidc.com/Linux/2014-08/105202.htm

Bash脚本15分钟进阶教程 http://www.linuxidc.com/Linux/2014-04/100750.htm

10个 Linux/Unix下 Bash 和 KSH shell 的作业控制实例 http://www.linuxidc.com/Linux/2014-03/98159.htm

Ubuntu下shell脚本运行异常:Bash和dash的区别 http://www.linuxidc.com/Linux/2013-10/91100.htm

Bash脚本之for语句if语句以及各种测试语句 http://www.linuxidc.com/Linux/2013-07/87922.htm

什么是Bash Shell的内建(build in)命令 http://www.linuxidc.com/Linux/2013-06/86039.htm

分享有用的 bash 别名和函数 http://www.linuxidc.com/Linux/2015-01/111178.htm

Linux Bash Shell入门教程 http://www.linuxidc.com/Linux/2013-08/8848.htm


本文永久更新链接地址
http://www.linuxidc.com/Linux/2015-03/115300.htm

原文:http://www.linuxidc.com/Linux/2015-03/115300.htm

shell: 深入理解 bash redirection 重定向

stdout redirection

[email protected]  cat 123
11111111
22222222
33333333
➜  [email protected]  cat 123 >> abc
➜  [email protected]  echo "one line>" >> abc
#当cat不带参数的时候,表示使用标准输入作为输入,这允许在标准输入中键入相关的内容
➜  [email protected]  cat >> abc
44444444
55555555
66666666^C    # ctrl+C
➜  [email protected]  cat abc
11111111
22222222
33333333
one line
44444444
55555555
66666666 

参考文档

stderr to stdout

[email protected]  cat > find.sh
find . -name "*>" -print -exec grep "555>" {} ;
^C
➜  [email protected]  sudo chmod +x find.sh
➜  [email protected]  ./find.sh
.
grep: .: 是一个目录
./abc
55555555
./nginx-V
./find.sh
find . -name "*>" -print -exec grep "555>" {} ;
./123
#第一种情况
➜  [email protected]  ./find.sh 2>&1 > find1.log
grep: .: 是一个目录
grep: 输入文件 ‘./find1.log’ 同时也作输出
#第一种情况
➜  [email protected]  ./find.sh > find2.log 2>&1
#结果1
➜  [email protected]  cat find1.log
.
./abc
55555555
./nginx-V
./find.sh
find . -name "*>" -print -exec grep "555>" {} ;
./123
./find1.log
#结果2
➜  [email protected]  cat find2.log
.
grep: .: 是一个目录
./abc
55555555
./nginx-V
./find.sh
find . -name "*>" -print -exec grep "555>" {} ;
./123
./find1.log
55555555
find . -name "*>" -print -exec grep "555>" {} ;
./find2.log
grep: 输入文件 ‘./find2.log’ 同时也作输出
 

0 是 stdin

1 是 stdout

2 是 stderr

./find.sh 2>&1 > find1.log

./find.sh > find2.log 2>&1

这里分析的关键是:一步一步分析,分析一步,输出一步

  • 第一种情况:

    • 2>&1: 将stderr定向到stdout, 原本stdout就是要到屏幕的,所以stderr会输出到屏幕
    • >find1.log: 将stdout 再重定向到文件
  • 第二种情况:

    • >find2.log: 将stdout重定向到文件
    • 2>&1: 将stderr重定向到stdout, 此时stdout已经到文件了,自然stderr也要到文件

重定向的过程其实很简单,但由于和直观感受不一致,往往导致初学者在这里犯很多错误。 参考文档

基本的IO重定向

基本IO重定向操作

  • > file: 将stdout重定向到file
  • < file: 将file作为stdin
  • cmd1 | cmd2 : pipe,将cmd1 的标准输出作为cmd2 的标准输入
  • >>file:将标准输出重定向到file,如果file存在,append到文件中,即附加到文件的后面,而不是覆盖文件
  • cat >> file: 当cat不带参数的时候,表示使用标准输入作为输入,这允许在标准输入中键入相关的内容
  • > | file: 强制将标准输出重定向到file,即使noclobber设置。当设置环境变量set –o noclobber,将禁止重定向到一个已经存在的文件中,避免文件被覆盖。
  • n >|file: 强制将文件描述符n重定向到file,即使noclobber打开
  • <>file: 将file作为标准输入和标准输出。通常用于设备文件(/dev下面的文件),底层系统程序员可用之测试设备驱动,其他的很少用
  • n <>file: 将file作为文件描述符n的输入和输出
  • << label: Here-document; : 将shell的标准输入作为命令的输入,直到行中之包含label。这中间的输入成为here-document。

[email protected] cat >> msgfile <<. heredoc> this is the text of
heredoc> our message
heredoc> end with .
heredoc> . #这里<<.表明以.为结束。因此无需使用^D,而改用. ➜ [email protected] cat msgfile this is the text of our message end with . [/code]

  • n>file :将文件描述符n重定向到file
  • n :将file作为文件描述符的输入
  • n>>file :将文件描述符n的输出重定向到file,如果file存在,将输出append到文件后面
  • n>& :将标准输出复制到文件描述符n(Duplicate standard output to file descriptor n)
  • n<& :从文件描述符n复制标准输入(Duplicate standard input from file descriptor n)
  • n>&m :文件描述字n将一个copy至文件描述字m(File descriptor n is made to be a copy of the output file descriptor)
  • n<&m :文件描述字n作为文件描述字m中的一个拷贝(File descriptor n is made to be a copy of the input file descriptor)
  • &>file : 将标准输出和标准错误输出定向至文件file
  • <&- : 关闭标准输入
  • >&-: 关闭标准输出
  • n>&- : 关闭文件描述字作为输出(Close the output from file descriptor n)
  • n<&- :关闭文件描述字作输入(Close the input from file descriptor n)
  • n>&word: If n is not specified, the standard output (file descriptor 1) is used. If the digits in word do not specify a file descriptor open for output, a redirection error occurs. As a special case, if n is omitted, and word does not expand to one or more digits, the standard output and standard error are redirected as described previously.
  • n<&word : If word expands to one or more digits, the file descriptor denoted by n is made to be a copy of that file descriptor. If the digits in word do not specify a file descriptor open for input, a redirection error occurs. If word evaluates to -, file descriptor n is closed. If n is not specified, the standard input (file descriptor 0) is used.
  • n>&digit- : Moves the file descriptor digit to file descriptor n, or the standard output (file descriptor 1) if n is not specified.
  • n<&digit- : Moves the file descriptor digit to file descriptor n, or the standard input (file descriptor 0) if n is not specified. digit is closed after being duplicated to n.

文件描述符

文件描述符在bash中比较少用,从0开始用户表示进行的数据流,0表示标准输入,1表示标准输出,2表示标注错误输出,其他从3开始。

最为常用的场景是将错误消息输出到某个文件,可以加上2>file 到我们的命令中。

我们来看下面一个脚本的例子:

command > logfile 2>&1 &
  • >logfile表示command的标准输出重定向至文件logfile中
  • 2>&1,匹配n>&m,表示文件描述字2(command的标准错误输出)将copy一份采用文件描述字1(即标准输出),由于标准输出已经重定向logfile,这份copy也见将重定向至文件lofgile。我们可以用“abcd > logfile 2>&1 &”来验证这个效果。

下面可达到类似的效果:

command 2>&1 | tee logfile &

错误输出同样适用标准输出,通过pipe方式,见他们作为输入执行tee logfile。tee命令将它的标准输入copy至他的标准标准输出以及参数所带的文件中。和上面的命令不一眼这里即会在stdout 和logfile中同时输出。

其他文件描述字的重定向,例如<&n,通常用于从多个文件中读入或者写出。

  • <&- ,表示强制关闭标准输入
  • >&-,表示强制关闭标准输出
  • 1> ,等同于>
  • 0< ,等同于<

原文:http://www.cnblogs.com/ganiks/p/deep-in-bash-redirection.html

shell: 经典的Fork炸弹

Jaromil在2002年设计了最为精简的一个Linux Fork炸弹,整个代码只有13个字符,在shell中运行后几秒后系统就会宕机:

:() { :|:& };:

这样看起来不是很好理解,我们可以更改下格式:

:()
{
	:|:&
};
:

更好理解一点的话就是这样:

bomb()
{
	bomb|bomb&
};
:

因为shell中函数可以省略 function关键字,所以上面的十三个字符是功能是定义一个函数与调用这个函数,函数的名称为 :,主要的核心代码是 :|:&,可以看出这是一个函数本身的递归调用,通过 &实现在后台开启新进程运行,通过管道实现进程呈几何形式增长,最后再通过 来调用函数引爆炸弹.因此,几秒钟系统就会因为处理不过来太多的进程而死机,解决的唯一办法就是重启。

Bomb一下

秉着不作不死的心态,我们也来运行一下,于是我将矛头指向云主机,,我使用了国内的一个2G内存的云主机,首先在本地开启两个终端,在一个终端连接云主机后运行炸弹,几秒后再尝试用另外一个终端登录,效果可以看下面Gif图:

shell: 经典的Fork炸弹
shell: 经典的Fork炸弹

看,运行一段时间后直接报出了 -bash: fork: Cannot allocate memory,说明内存不足了。并且我在二号终端上尝试连接也没有任何反应。因为是虚拟的云主机,所以我只能通过主机服务商的后台来给主机断电重启。然后才能重新登录:

shell: 经典的Fork炸弹
shell: 经典的Fork炸弹

炸弹危害

Fork炸弹带来的后果就是耗尽服务器资源,使服务器不能正常的对外提供服务,也就是常说的DoS(Denial of Service)。与传统1v1、通过不断向服务器发送请求造成服务器崩溃不同,Fork炸弹有种坐山观虎斗,不费一兵一卒斩敌人于马下的感觉。更吓人的是这个函数是不需要root权限就可以运行的。看到网上有帖子说某些人将个性签名改为Fork炸弹,结果果真有好奇之人中枪,试想如果中枪的人是在公司服务器上运行的话,oh,!

预防方式

当然,Fork炸弹没有那么可怕,用其它语言也可以分分钟写出来一个,例如,python版:

import os
 	while True:
 	os.fork()

Fork炸弹的本质无非就是靠创建进程来抢占系统资源,在Linux中,我们可以通过 ulimit命令来限制用户的某些行为,运行 ulimit -a可以查看我们能做哪些限制:

[email protected]:~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7782
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7782
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
 

可以看到, -u参数可以限制用户创建进程数,因此,我们可以使用 ulimit -u 20来允许用户最多创建20个进程。这样就可以预防bomb炸弹。但这样是不彻底的,关闭终端后这个命令就失效了。我们可以通过修改 /etc/security/limits.conf文件来进行更深层次的预防,在文件里添加如下一行(ubuntu需更换为你的用户名):

ubuntu – nproc 20

这样,退出后重新登录,就会发现最大进程数已经更改为20了,

shell: 经典的Fork炸弹
shell: 经典的Fork炸弹

这个时候我们再次运行炸弹就不会报内存不足了,而是提示 -bash: fork: retry: No child processes,说明Linux限制了炸弹创建线程。

参考

http://en.wikipedia.org/wiki/Fork_bomb

原文:http://blog.saymagic.cn/2015/03/25/fork-bomb.html

shell: bashrc not work

今天想 在 .bashrc 中配置一段自动启动 ssh-agent 的脚本,结果总是没有自动运行;才发现我的 bashrc 脚本没有自动 加载

后来才发现是这次装的深度系统(deepin)默认没有 ~.profile脚本, 去看看之前的ubuntu系统里面都默认是有这个脚本的,而 ~.bashrc脚本则是通过 .profile 来加载的

如果新建一个用户, 在其 $HOME 目录下会自动创建 .profile 脚本吗?

1. linux系统加载bash配置脚本的顺序

.bashrc 文件本身在 *nix 系统下就不会自动加载,一般都是通过 .profile 间接加载的

一般,系统会按下面的顺序加载

/etc/profile
~/.bash_profile
~/.bash_login
~/.profile

如果你的 .bashrc没有自动加载,就新建 ~/.profile

# ~/.profile: executed by Bourne-compatible login shells.
if [ "$BASH>" ]; then
  if [ -f ~/.bashrc ]; then
    . ~/.bashrc
  fi
fi
mesg n         

当然如果, 已经有了 .bash_profileor .bash_login, 那么这个 .profile文件也不会被加载。 总之,是把 此段代码写到 已经存在的 最先被加载到的那个配置中。

refer to :

2. Difference Between .bashrc & .bash_profile

.bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.

  1. 当你直接在机器login界面登陆、使用ssh登陆或者su切换用户登陆时,.bash_profile 会被调用来初始化shell环境Note:.bash_profile文件默认调用.bashrc文件

  2. 当你不登陆系统而使用ssh直接在远端执行命令,.bashrc 会被调用
  3. 你已经登陆系统后,每打开一个新的Terminal时,.bashrc 都会被再次调用。

若要配置环境变量之类,最保险是写在 .bashrc 文件中。因为不管是登陆还是不登陆,该文件总会被调用

refer to :

http://upgirl.blog.51cto.com/3744514/1140176

原文:http://www.cnblogs.com/ganiks/p/bashrc-not-work.html

shell: 【应用】:shell crontab定时生成oracle表的数据到txt文件,并上传到ftp

一、本人环境描述

1、oracle服务端装在win7 32位上,oracle版本为10.2.0.1.0

2、Linux为centos6.5 32位,安装在Oracle VM VirtualBox虚拟机上

3、win7上装有ftp服务

二、功能实现描述用shell的crontab命令定时执行某个.sh文件,此文件的功能已实现生成oracle表的数据到本地txt文件,并上传到ftp,必要时可记录执行日志。

2、 在centos中安装ftp客户端

3、 编写shell,实现查询oracle数据库表,并写到本地txt文件

4、 编写shell,实现上传文件到ftp

5、修改shell,打印执行日志

打印日志函数如下:

function  loginfo {
  time_flag =`date +" %Y-%m-%d %H:%M:%S >" `
  echo  " [${time_flag}] [INFO] -- $1 >"
}  

View Code

6、所有shell代码

数据表结构见【 编写shell,实现查询oracle数据库表,并写到本地txt文件

A、把打印日志函数封装成testLog.sh,代码如下:

# !/bin/bash
# #####################################################################################
# 功能:定义日志打印函数
# 用法:loginfo “日志内容”
# 版本:0.1      #作者:crazyMyWay      #日期:
# 说明:建立初版
# #####################################################################################
function  loginfo {
  time_flag =`date +" %Y-%m-%d %H:%M:%S >" `
  echo  " [${time_flag}] [INFO] -- $1 >"
}  

View Code

B、通过ftp上传文件代码封装成testFtptool.sh,如下:

# !/bin/bash
# #####################################################################################
# 功能:ftp上传/下载文件
# 用法:第一个参数put(上传)还是get(下载)文件,第二个参数为FTP服务器IP,第三、四个参数分别是用户名和密码
#       第五个参数是FTP上的工作目录,第六个是本地的目录,第七个是操作的文件名
# 例子:testFtptool.sh put|get ip_address ftp_user ftp_password ftp_dir local_dir filename
# 版本:0.1    #作者:crazyMyWay     #日期:
# 说明:建立初版
# #####################################################################################
E_NOTROOT=67
# 输出帮助信息,用法:./testFtptool.sh -h
if  [ $#  -eq 1 -a "$1>" = "-h>" ]
then
  echo  " Usage: $0 put|get ip_address ftp_user ftp_password ftp_dir local_dir filename >"
  echo  " Example:
        $0 put|get ftp服务ip ftp用户名 ftp密码 ftp目录 本地目录 文件名 >"
  exit  $E_NOTROOT
fi
 # 如果参数不等于7
if  [ $#  != 7 ]
then
  echo  " Param error: Usage: $0 put|get ip_address ftp_user ftp_password ftp_dir local_dir filename >"
  exit  $E_NOTROOT
fi
 # 进行ftp操作,ftp命令解释请查阅相关资料
ftp -v -n <<!
open  $2  21
user  $3  $4
prompt
epsv4 off
cd  $5
bin
lcd  $6
$1  $7
quit
 ! &#91;/code&#93;
<span>View Code
</div>
<p>C、主要代码testStudent.sh,如下:</p>
<div>
<img src="http://img1.tuicool.com/7JJJry.gif" />

# !/bin/bash
# #####################################################################################
# 功能:从oracle中查询数据(t_student),并写到txt文件中,以student_yyyymmdd.txt命名,
#       最后上传到ftp
# 用法:定时调度执行,每天凌晨2点执行(或直接执行)
#       注意修改:user/[email protected]、
#       引入testLog.sh和testFtptool.sh的路径、
#       ftp-ip、ftp-username、ftp-password、ftp上传目录、本地目录
#
# 版本:0.1      #作者:crazyMyWay      #日期:2015-03-29
# 说明:建立初版
# #####################################################################################
# 加入用户环境变量,如果不执行这句,那么在用cron命令时,
# 不会自动加载用户的环境变量,如果用到sqlplus之类命令,因此会出错
. ~/.bash_profile
 # 定义文件后缀名称yyyymmdd
filename_postfix=`date +" %Y%m%d >" `
 # 定义相关变量
oracle_user=" centos >"
oracle_pass =" centos >"
oracle_id =" win7orcl >"
current_file_dir =" /ljxd/shell-demo/oracle/ >"
current_file_name =" student_${filename_postfix}.txt >"
common_file_dir =" /ljxd/shell-demo/oracle/ >"
ftp_ip =" 192.168.56.101 >"
ftp_user =" student >"
ftp_pass =" student >"
ftp_upload_path =" /student >"
# 引入log文件
. ${common_file_dir} testLog.sh
loginfo  " generate data start........ >"
# 连接到oracle,设置相关参数,并输出数据到txt文件
sqlplus -s ${oracle_user} /${oracle_pass} @${oracle_id}  <<eof >${current_file_dir}${current_file_name}
set pages  0
set feed off
set heading off
set feedback off
set verify off
set linesize  1000
select t.id ||'# ##'||t.name||'###'||to_char(t.birthday,'yyyy-mm-dd hh24:mi:ss') from t_student t;
EOF
 # 推数据到ftp
loginfo " transfer data to ftp....... >"
.  ${common_file_dir} testFtptool.sh put ${ftp_ip}  ${ftp_user}  ${ftp_pass}  ${ftp_upload_path}  ${current_file_dir}  ${current_file_name}
# end
loginfo " generate data end......... >"  

View Code

注意目录结构,修改相关参数,运行./testStudent.sh即可

测试结果如下:

shell: 【应用】:shell crontab定时生成oracle表的数据到txt文件,并上传到ftp
shell: 【应用】:shell crontab定时生成oracle表的数据到txt文件,并上传到ftp

7、crontab命令实现定时任务

crontab -e|-l|-r

-e|-l|-r分别为编辑、查看、删除定时任务,每个用户下会有一个crontab配置文件,详细说明请查阅相关资料。

每天凌晨2点定时调度执行,并把输出日志追加到student.log文件中,crontab命令如下:

保存并退出编辑器,定时器立即生效。

原文:http://www.cnblogs.com/crazyMyWay/p/4371522.html

shell: shell grep正则匹配汉字

Shell grep正则匹配中文

测试文本 demo_exe.c,内容如下,需要注意保存的编码格式,对输出到终端有影响:

我们中文操作系统ASNI默认是GBK的。

 1  #include<stdio.h>
 2  #include<stdlib.h>
 3  #include <string .h>
 4  #include <errno.h>
 5  #include <locale.h>
 6  #include <dlfcn.h>
 7
 8  /*
 9   * export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/local/tmp; /data/local/tmp/demo_exe
 10  */
11  int  main(int  argc, char ** argv) {
 12  //  这个是中文
13  void  *handle = NULL;
 14  char * locname = setlocale(LC_ALL, ">" );
 15  //  这个是中文
 16  //
 17  if  ((handle = dlopen(demo_dso_so, RTLD_NOW)) == NULL) {
 18          printf(" dlopen出错: %sn >" , dlerror());
 19      }
 20      printf(" @%s[%s]dlopen return handle = %#x.n >" , __FILE__, __FUNCTION__, handle);
 21  //  这个是
 22  //  中文
23  return  0 ;
 24  } 

1、匹配特定文字:

$ grep -nP “xE4xB8xADxE6x96x87|xD6xD0xCExC4>” ./demo_exe.c

12:// 这个是中文

15:// 这个是中文

22:// 中文

编码 在线码表
GBK D6D0 CEC4 http://www.lhelper.org/tech/chinese_internal_code_specification_classified.txt
Unicode 4E2D 6587
UTF-8 %E4%B8%AD %E6%96%87 http://wenku.baidu.com/link?url=DfbzjKLcRaQ7yVIA_EHVP7mKdVbkggq4hwkCmmO9uR76Jib_5Y1Y_h616NnI21XY_x85YZqN1SQBAdCFQjklS_

GBK码 : 中=D6D0,文=CEC4

Unicode码:中=4E2D,文=6587

UTF-8码:中=%E4%B8%AD,文=%E6%96%87

2、匹配特定范围文字

$ grep -nP “[xB0xA1-xF7xFE]+>” /home/fangss/c/dynamic_share_object_test/demo_exe.c

12:// 这个是中文

15:// 这个是中文

18: printf(“dlopen出错: %sn>”, dlerror());

21:// 这个是

22:// 中文

范围:

● GBK/2: GB2312 汉字
B0 0 1 2 3 4 5 6 7 8 9 A B C D E F
A   啊 阿 埃 挨 哎 唉 哀 皑 癌 蔼 矮 艾 碍 爱 隘
B 鞍 氨 安 俺 按 暗 岸 胺 案 肮 昂 盎 凹 敖 熬 翱
C 袄 傲 奥 懊 澳 芭 捌 扒 叭 吧 笆 八 疤 巴 拔 跋
D 靶 把 耙 坝 霸 罢 爸 白 柏 百 摆 佰 败 拜 稗 斑
E 班 搬 扳 般 颁 板 版 扮 拌 伴 瓣 半 办 绊 邦 帮
F 梆 榜 膀 绑 棒 磅 蚌 镑 傍 谤 苞 胞 包 褒 剥
。。。 
F7 0 1 2 3 4 5 6 7 8 9 A B C D E F
A   鳌 鳍 鳎 鳏 鳐 鳓 鳔 鳕 鳗 鳘 鳙 鳜 鳝 鳟 鳢
B 靼 鞅 鞑 鞒 鞔 鞯 鞫 鞣 鞲 鞴 骱 骰 骷 鹘 骶 骺
C 骼 髁 髀 髅 髂 髋 髌 髑 魅 魃 魇 魉 魈 魍 魑 飨
D 餍 餮 饕 饔 髟 髡 髦 髯 髫 髻 髭 髹 鬈 鬏 鬓 鬟
E 鬣 麽 麾 縻 麂 麇 麈 麋 麒 鏖 麝 麟 黛 黜 黝 黠
F 黟 黢 黩 黧 黥 黪 黯 鼢 鼬 鼯 鼹 鼷 鼽 鼾 齄 

原文:http://www.cnblogs.com/Fang3s/p/4414914.html

shell: Shell或命令行计算数组或文件的行数和列数

(一)闲聊Linux Shell 编程

都说中国文化博大精深(例如汉字),但作为操作系统中的佼佼者,Linux虽然时间并不长,但同样也是博大精深。谁也不敢说自己已经熟练的掌握了Linux中所有的内容,除了知识点众多以外,快速的发展和更新使得Linux越来越强大,也使得Linux在短时间内越来越难掌握。所以说,知识真是一个积累的过程,但有时候脑袋还真记不住,比如Linux Bash里面的变量替换、Bash变量展开等,如果感觉自己进展不顺利就赶紧用笔记吧。

学过Java、php、python、shell等再回来学C,发现C真的是很难。难点在哪?感觉拿到C以后真的无从下手,作为Java来说,极好的IDE、完善的文档和众多的学习人数使得获取Java帮助并不难。对于php、python、shell等脚本语言来说,丰富的函数库介绍和帮助系统对于英语熟练的人来说非常简单。而作为C这一古老的语言,要想查看它的函数库和帮助系统,可能是自己还没有真正的认识C,正因如此我颇感到有心无力。

回过头来再说Shell,Bash Shell在Linux系统管理和维护中往往发挥出巨大的作用,系统管理、自动化、监控报警、计划任务等样样精通。几乎在Linux下能想到的功能,甚至系统函数中的功能,都有Linux命令与之对应,Linux命令的强大使得Shell也变得强大。Shell本身也是程序,有人说程序=算法+数据结构,但对于Shell而言,程序=算法+命令,因为Shell 是解释型语言,它的变量都是弱类型(Java、C等都是强制类型),由此可知命令对于Shell来说多么重要。

但当你想用Shell处理一些它不擅长的操作时,你就会觉得这挺痛苦,尽管这个想法本身也是痛苦的,毕竟Shell也不是万能的。比如你想用Bash Shell实现二维数组,还想有若干的命令或函数去处理二维数组,那真是很不容易,尽管你可以将二维数组看作是特殊的一维数组。

Linux像UNIX一样,程序间的标准接口都是文本(即所谓的文本流),Linux用文本流传递数据,最能体现文本流的就是管道。如果你观察仔细,Linux中的许多命令的输出都是看起来以某种格式格式化了的。看起来像数组,像矩阵,这就是为什么我想把数组放到题目中去。由于文本流的存在,命令的输出可以变成普通文件,它看起来就像一个数组,特别像一个二维数组。如何操作这些输出其实也可以看成操作一个二维数组。

Shell编程的核心,除了需要对大量命令的熟练掌握和设计合适的算法(包括程序结构)外,对于数据的处理越来越重要,对于别的程序而言同样也是对数据(数据库)的增删改查。我观察到几乎所有的数据处理都是按照行和列的形式处理的,打印/替换/删除/增加多少行多少列的内容,想想sed、awk这些程序想必很容易联想的到。

(二)Shell或命令行计算数组或文件的行数和列数

也许计算行数对于Linux世界是最重要的,有很多种方法。

1.awk + tail

command | awk '{print NR}' | tail -n1
command | awk 'END{print NR}'

2.grep + awk

command | grep -n ">" | awk -F ":>" '{print $1}' | tail �n1 

3.sed

command | sed -n "$=>"

4.wc

command | wc �l

计算列数

1.思路将二维数组通过head -n1抽取成一维数组,通过${#val[@]}计算一维数组长度,从而获取列数

a=(`command | head -n1`) && echo ${#a[@]}

2.直接利用awk计算列数(要求command的输出中每一列都是有数据的,不能与awk的FS冲突,例如如果awk以空格为FS间隔符,则每一列的数据中不能有空格,否则容易出错)

command | head -n1 | awk -F ' ' '{print NF}'
command | awk -F ' ' '{print NF}' | head �n1 

(三)应用举例:找出数组(矩阵)中缺值的列,或剔除缺值的列

例如有一个文件的内容如下

1 1 2 3

1   3 5    

2 3 4    

1 2 3 4

通过Shell脚本将其变为

1 2

1 3    

2 4    

1 3

思路:

(1)分析每一列的行数,如果列的行数小于最大行数,则该列无效,将其剔除。

(2)考虑到有可能某一列全为空,例如这一列没有数据,并与awk用的FS值相同,则考虑将相邻两列相同的合并为一列。例如有一个文件的内容如下:

1 1 2 3   3

1   3 5   4    

2 3 4     7    

1 2 3 4   7    

5   5     8    

1 3 4 5   5

将空格换成a:

1a1a2a3aaa3

1aaa3a5aaa4    

2a3a4aaaaa7    

1a2a3a4aaa7    

5aaa5aaaaa8    

1a3a4a5aaa5

就应该把8、9、10列合并成一列,变为:

1a1a2a3a3

1aaa3a5a4    

2a3a4aaa7    

1a2a3a4a7    

5aaa5aaa8    

1a3a4a5a5

再变为:

1 1 2 3 3

1   3 5 4    

2 3 4   7    

1 2 3 4 7    

5   5   8    

1 3 4 5 5

此时再经过处理以后就会变为

1 2 3

1 3 4    

2 4 7    

1 3 7    

5 5 8    

1 4 5

–end–

原文:http://dgd2010.blog.51cto.com/1539422/1630920

shell: 编写属于自己的linux命令

开篇: 问题和解决思路

在使用一些基础IDE时,工具经常会在我们建立特定文件时给我们一个已经有了一些特定代码的模板文件,但是在linux开发时,没有这样的IDE,怎么办?虽然代码量不是很多,但是能一次简化它和IDE一样也是一件让人心情愉悦的事情

html文件中:

1
2
3
4
5
6
7
8
9
10
” “http://www.w3.org/TR/html4/loose.dtd>”>

<html>
<head>
<metahttp-equiv=“Content-Type>”content=“text/html; charset=UTF-8>”>
<title>Insert title heretitle>
head>
<body>
body>
html>

php文件中:

1
2
3
4
5
filename:*****author :*****

或者这样:

shell文件中:

#!/bin/bash

Perl文件中:

#!/usr/bin/perl

Python文件中:

#!/usr/bin/python

每次都写这么无聊的东西 实在是浪费时间,我也相信那就话:不懒的程序员不是一个好的程序员,

所以让我们自己动手写一个数据自己的命令,我们的思路还是那样,利用linux启动加载的机制:

利用login

login shell:取得 bash 时需要完整的登陆流程的,就称为 login shell

/etc/profile -> ~/.bash_profile(~/.bash_login、~/.profile,bash 的 login shell 配置只会读取上面三个文件的其中一个,顺序从左到右)

/etc/profile文件:

~/.bash_profile文件: 

这里注意这几个文件: 这是一个可以让我们自由定制属于自己的bash的配置文件(例如这里你可以 alias 设置属于你自己的别名)、面向全系统的配置那就是 /etc/bashrc 了

那这个文件如何加载到bash环境中?

再来看看我们 ~/.bash_profile 中 写了什么,所以你在 .bashrc 中定义的alias别名才会在系统开机时加载到环境中

这是一个当你退出shell环境是执行的一些操作的设置

这是记录你执行过bash命令的一个历史记录文件

过程的错误

注意:这里我犯了一个严重的错误,我将我的new.sh文件放到  /etc/profile.d/ 目录下,结果就是我无法登录了!!!!  最后使用救援模式才把系统救了回来,看到这里大家一定要注意,++中间的是错误的

好了,我们分析一下为什么?

现象是:我已输入用户名/密码 系统就立即exit到了登录界面

当我在救援模式下删除了/etc/profile.d下的new.sh文件时,我才意识到:/etc/profile文件中

这段代码意思是:当登录时会执行 /etc/profile.d/ 目录下所有的 .sh文件,当系统执行我的new.sh文件时,我的new.sh文件要求 参数没有的话就 exit退出了,哎,就是这么粗心的问题

那么正确的思路应该是:

echo $PATH

我选择将文件放到 /usr/local/bin 目录下 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

由于我们想让我们写的这些命令可以被系统中所有用户使用,那我们就要对 /etc/profile 这个文件下手了!!!

看看 /etc/profile/ 中的内容就会明白,这个文件里面是一系列关于登录用户取得shell后的环境信息,我们可以将我们的这个执行命令放到这个文件中

但是最好还是别修改这个 文件,我们有更好的办法;这个文件在最后有一个处理就是将 /etc/profile.d文件夹下的所有可执行的 *.sh 文件加入shell

环境中去,所以我们的思路就是把我们写好的 shell 脚本放到这个目录下去

让我们看看 /etc/profile 这个文件中关于 profile.d中文件的加载

再来看看 /etc/profile.d/文件夹下文件

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

注意将我们写好的 shell脚本所有用户可读和可执行权限

实现篇:

根据我们上面了解知识和思路,我们开始我们的实现步骤,详细过程就不说了,太繁琐了,我就简单的在代码中注释了,本身没有什么难道,有点基础的相信都没问题

设置命令格式:

代码实现:

新建一个new.sh文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/bin/bash#+++++++++++++++++++++++++++++++++++# filename: new.sh# author: wangxb# date: 2015-04-11 00:08:59#+++++++++++++++++++++++++++++++++++#——————————————————————————————————————————————# 由于在linux下开发时经常需要在新建文件后,输入一下信息,类似于这样:# # filename:*****# author :*****# 或者这样:# shell文件中: #!/bin/bash# Perl文件中: #!/usr/bin/perl# Python文件中:#!/usr/bin/python# 每次都写这么无聊的东西 实在是浪费时间,我也相信那就话:不懒的程序员不是一个好的程序员,# 所以让我们自己动手写一个数据自己的命令,我们的思路还是那样,利用linux启动加载的机制:# 利用login# login shell:取得 bash 时需要完整的登陆流程的,就称为 login shell# /etc/profile -> ~/.bash_profile(~/.bash_login、~/.profile,bash 的 login shell 配置只会读取上面三个文件的其中一个,顺序从左到右)# 由于我们想让我们写的这些命令可以被系统中所有用户使用,那我们就要对 /etc/profile 这个文件下手了!!!# 看看 /etc/profile/ 中的内容就会明白,这个文件里面是一系列关于登录用户取得shell后的环境信息,我们可以将我们的这个执行命令放到这个文件中# 但是最好还是别修改这个 文件,我们有更好的办法;这个文件在最后有一个处理就是将 /etc/profile.d文件夹下的所有可执行的 *.sh 文件加入shell# 环境中去,所以我们的思路就是把我们写好的 shell 脚本放到这个目录下去# 注意将我们写好的 shell脚本所有用户可读和可执行权限# —————————————————————————————————————————————–# 设置模板文件存放路径

TPL_DIR=“/root/mylinux/myCommand/newtpl/tpl>”

# 这里是根据命令的第一个参数来确定调用什么样的模板文件和默认的生成文件的后缀名

case$1in
‘html’)
TPL_NAME=“html.tpl>”
suffix=“html>”

;;

‘html5’)
TPL_NAME=“html5.tpl>”
suffix=“html>”

;;

‘php’)
TPL_NAME=“php.tpl>”
suffix=“php>”

;;

‘css’)
TPL_NAME=“css.tpl>”
suffix=“css>”

;;

‘js’)
TPL_NAME=“jss.tpl>”
suffix=“js>”

;;

‘py’)
TPL_NAME=“py.tpl>”
suffix=“py>”

;;

‘pl’)
TPL_NAME=“pl.tpl>”
suffix=“pl>”

;;

‘rb’)
TPL_NAME=“rb.tpl>”
suffix=“rb>”

;;

‘sh’)
TPL_NAME=“sh.tpl>”
suffix=“sh>”

;;*)

echo“command type now exist>”

exit;;esac

exportTPL_DIR
exportTPL_NAME

# 根据特定格式模板文件创建一个我们想要的文件的方法

functioncreateTpl() {
filename=“$1.$2>”  
# 设置文件名
localdir=${3} # 设置文件目录

# 判断在目标目录下是否存在同名文件,对于[存在/不存在]进行相应处理

if[ -f $localdir/$filename ];then
create_date=$(date+“%Y%m%d%H%M%S>”)
read-p“${filename} is exist, Do you want to ${1}_${create_date}.${suffix}.(y/n)>”yes_no
if[“$yes_no>”=‘y’] || [“$yes_no>”=“Y>”] || [“$yes_no>”=“yes>”] || [“$yes_no>”=“YES>”];then

filename=${1}_${create_date}.${suffix}

elif[“$yes_no>”=‘n’] || [“$yes_no>”=“N>”] || [“$yes_no>”=“no>”] || [“$yes_no>”=“NO>”];then

exitfifi# 判断模板文件是否存在# 存在:根据模板文件生成我们的文件,并自动替换其中的文件名、时间和创建者

if[ -e ${TPL_DIR}/${TPL_NAME} ];then
touch$localdir/$filename >/dev/null2>&1
cat$TPL_DIR/$TPL_NAME > $localdir/$filename 2>/dev/null
cdate=$(date+“%Y_%m_%d %H:%M:%S>”)
sed-i“s/@filename/$filename/g>”$localdir/$filename
sed-i“s/@cdate/$cdate/g>”$localdir/$filename
if[ $# -eq 4 ]; then
sed-i“s/@author/$4/g>”$localdir/$filename

else

who=$(whoami)
sed-i“s/@author/$who/g>”$localdir/$filename

fivim $localdir/$filenameelse# 不存在:就创建一个空文件即可

touch$localdir/$filename >/dev/null2>&1

vim $localdir/$filenamefi}# 检查数据目录是否是一个有效的目录

functioncheckDir() {
if[“$1>”=“>”];then
localdir=$(pwd)

else

$(cd$1 >/dev/null2>&1) &&cd$1 >/dev/null2>&1 ||exit
localdir=$(pwd)

fi

echo$localdir

}# 检查输入的文件后缀是否符合要求

functioncheckSuffix() {
suffix=
if[[“$1>”=~ ^[a-zA-Z0-9]+$ ]];then

suffix=$1fi

echo$suffix

}# 左移我们的参数列表shift# 检查必填参数文件名情况

if[“$#>”-lt 1 ] || [“$1>”=“>”];then
echo“Command request file name(not allow empty) as first options>”

exitfi# 对于数据的可选参数,根据输入参数 进行不同处理

case$# in

1)

createTpl $1 $suffix $(pwd)

;;2)localdir=$(checkDir $2)

if[ -z“$localdir>”];then
echo‘The directory does not exist’

exitficreateTpl $1 $suffix $localdir;;3)localdir=$(checkDir $2)

if[ -z“$localdir>”];then
echo‘The directory does not exist’

exitfi

if[ -z“$(checkSuffix $3)>”];then
echo‘suffix format is error’

exitelsesuffix=$(checkSuffix $3)ficreateTpl $1 $suffix $localdir;;4)localdir=$(checkDir $2)

if[ -z“$localdir>”];then
echo‘The directory does not exist’

exitfi

if[ -z“$(checkSuffix $3)>”];then
echo‘suffix format is error’

exitelsesuffix=$(checkSuffix $3)fi

if[[“$4>”=~ ^[a-zA-Z]+$ ]];then

author=$4else

author=$(whoami)

ficreateTpl $1 $suffix $localdir $author;;*)

echo“options nums is error>”

exit;;esac

建立tpl模板文件:

html.tpl:

1
2
3
4
5
6
7
8
9
10
” “http://www.w3.org/TR/html4/loose.dtd>”>

<html>
<head>
<metahttp-equiv=“Content-Type>”content=“text/html; charset=UTF-8>”>
<title>Insert title heretitle>
head>
<body>
body>
html>

php.tpl

/** filename: @filename* author : @author* create : @cdate* update : @update*/

sh.tpl

1
2
3
4
5
6
7
8
#!/bin/bash#+++++++++++++++++++++++++++++++++++++++++++++++++# filename : @filename# author : @author# create : @cdate# update : @update#+++++++++++++++++++++++++++++++++++++++++++++++++

设置系统加载和alias 建立别名 

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

根据我们开篇的知识我们复制我们的new.sh文件到 /etc/profile.d文件夹下:

设置执行权限

复制过来发现,我们文件的权限和其他文件一致,所以我们就不做修改了

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

复制 复制我们的new.sh文件到 /usr/local/bin文件夹下,并更名为 new,修改权限可执行

测试:

OK 命令存在

复制我们的模板文件到 /var/tpl 目录下

cp -r /root/mylinux/myCommand/newtpl/tpl /var/

修改new.sh文件中的TPL_DIR变量

alias设置别名 修改 /etc/bashrc 文件,在文件末尾追加

完工

激动的时候来了,我们试试执行我们的命令

新建html

新建php

看到么,初始化文件信息已经完成

新建 shell文件

再来看看,html和shell文件已经在当前目录下生成,php文件则在我们的相对目录下生成

结语

至此,一套属于我们自己的命令就已经完成,万事开头难,昨天突然有了这个小想法,硬着头皮开始做,现在弄完了觉得非常开心。嘿嘿 洗洗睡觉了

来自为知笔记(Wiz)

原文:http://www.cnblogs.com/wxb0328/p/mycommand.html

shell: Ubuntu Shell脚本编码问题

今天一同事在写一个数据库备份的shell脚本,在多次确定脚本代码无误的情况下,发现脚本输出的结果死活不正常。

/* *
 * @author jenkiHuang
 * @email [email protected]
 * @version 20150407
 * /
#!/bin/bash
DATA_DIR="/home/oracle/bakup/data>"
LOGS_DIR="/home/oracle/bakup/logs>"
DELTIME=`date -d "7 days ago>" +%Y%m%d`
BTM=`date "+%Y%m%d%H%M%S>"`
FILENAME="$DATA_DIR$BTM.dmp>"
echo "Starting bakup...>"
echo $FILENAME  

在对文件进行可执行权限设置后,执行脚本时输出

sudo  ./oracleautobk.sh
Starting bakup...
.dmp0407165921akup /data 

上面的第二条Echo语句明显不对,无奈在网上各种找资料,最后在Bing(很少用度娘搜索,Google搜索大家都懂的)中找到关于shell脚本编码的问题。原来那同事在编写脚本的时候不是用的vi编辑器直接编写。而是在windows上面用UE编写后,用ftp工具传到linux系统中。那么现在问题来了,在windows系统中编写的shell脚本的默认格式是dos而不是unix,所以造成输出结果不正确。

查看shell脚本的格式,用vi编辑shell脚本。然后输入”:set ff?>”如果输出结束是”fileformat=dos>”,则需要修改文件的格式

// 修改文件格式,用vi打开shell脚本后输入
:set ff=unix
 // 然后保存退出  

再次执行脚本文件,可以正确输出年月日格式的文件名

sudo  ./oracleautobk.sh
Starting bakup...
 /home/oracle/bakup/data20150407171543.dmp 

所以在这看来,以后编写脚本还是直接在linux系统中使用vi编写更为实在。一来熟练了vi编辑器,二来还可以避免带来不必要的麻烦。

转载: http://www.jenkihuang.com/experience/2015/04/ubuntu-shell-charset.html

原文:http://www.cnblogs.com/jenkiHuang/p/4424965.html

shell: 企业合格的linux运维必会shell编程题

企业合格的linux运维必会编程题,能独立完成的同学就业工资不会低于10K

这是 老男孩linux运维班
要求学生必会的题目,完不成的不能合格毕业,每个完成的都奖励价值500-1000元的等值礼物(以当天考试成绩宣布为准),要进要退自己抉择,伙伴们走起!

实战考试时间就在2015年4月15日上机实战,禁止大面积抄袭学习课堂笔记否则无奖励!
>
共18道考试题,面授上课几乎全部讲解过类似的案例,考试题略微变更而已。

企业面试题1:

(生产实战案例):监控MySQL主从同步是否异常,如果异常,则发送短信或者邮件给管理员。提示:如果没主从同步环境,可以用下面文本放到文件里读取来模拟:

阶段1:开发一个守护进程脚本每30秒实现检测一次。

阶段2:如果同步出现如下错误号(1158,1159,1008,1007,1062),则跳过错误。

阶段3:请使用数组技术实现上述脚本(获取主从判断及错误号部分)

[[email protected]~]# mysql -uroot -p'oldboy' -S /data/3307/mysql.sock -e "show slavestatusG;>"
*************************** 1. row ***************************
               Slave_IO_State:Waiting for master to send event
                  Master_Host:10.0.0.179   #当前的mysql master服务器主机
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File:mysql-bin.000013
         Read_Master_Log_Pos: 502547
               Relay_Log_File:relay-bin.000013
                Relay_Log_Pos:251
        Relay_Master_Log_File:mysql-bin.000013
             Slave_IO_Running:Yes
           Slave_SQL_Running: Yes
              Replicate_Do_DB:
         Replicate_Ignore_DB: mysql
          Replicate_Do_Table:
      Replicate_Ignore_Table:
     Replicate_Wild_Do_Table:
 Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
         Exec_Master_Log_Pos: 502547
              Relay_Log_Space:502986
              Until_Condition:None
               Until_Log_File:
                Until_Log_Pos: 0
          Master_SSL_Allowed: No
          Master_SSL_CA_File:
          Master_SSL_CA_Path:
              Master_SSL_Cert:
           Master_SSL_Cipher:
               Master_SSL_Key:
       Seconds_Behind_Master: 0   #和主库比同步延迟的秒数,这个参数很重要
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error: 

企业面试题2:
使用for循环在/oldboy目录下通过随机小写10个字母批量创建10个html文件,名称例如为:

[[email protected] oldboy]# sh /server/scripts/oldboy.sh
[[email protected] oldboy]# ls -l
total 0
-rw-r--r-- 1 root root 0 Apr 15 11:34coaolvajcq_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34gmkhrancxh_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34jdxexendbe_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34qcawgsrtkp_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34qnvuxvicni_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34tmdjormaxr_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34ugaywanjlm_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34vfrphtqjpc_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34vioesjmcbu_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34wzewnojiwe_oldboy.html
-rw-r--r-- 1 root root 0 Apr 15 11:34xzzruhdzda_oldboy.html 

企业面试题2:请用至少两种方法实现!
将以上文件名中的oldboy全部改成oldgirl(用for循环实现),并且html改成大写。

企业面试题3:
批量创建10个系统帐号oldboy01-oldboy10并设置密码(密码为随机8位字符串)。

企业面试题4:
写一个脚本,实现判断10.0.0.0/24网络里,当前在线用户的IP有哪些(方法有很多)

企业实战题5:请用至少两种方法实现!

写一个脚本解决DOS攻击生产案例

提示:根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100,即调用防火墙命令封掉对应的IP,监控频率每隔3分钟。防火墙命令为:iptables-A INPUT -s 10.0.1.10 -j DROP。

企业实战题6:

开发mysql多实例启动脚本:

已知mysql多实例启动命令为:mysqld_safe–defaults-file=/data/3306/my.cnf &

停止命令为:mysqladmin -u root -poldboy123 -S /data/3306/mysql.sockshutdown

请完成mysql多实例启动启动脚本的编写

要求:用函数,case语句、if语句等实现。

企业实战题7:如何实现对MySQL数据库进行分库备份,请用脚本实现

企业实战题8:如何实现对MySQL数据库进行分库加分表备份,请用脚本实现

企业面试题9:请用至少两种方法实现!

bash for循环打印下面这句话中字母数不大于6的单词(昆仑万维面试题)。

I am oldboy teacher welcome to oldboy training class.


>

企业面试题10:

开发shell脚本分别实现以脚本传参以及read读入的方式比较2个整数大小。以屏幕输出的方式提醒用户比较结果。注意:一共是开发2个脚本。当用脚本传参以及read读入的方式需要对变量是否为数字、并且传参个数做判断。
 

企业面试题11:
打印选择菜单,一键安装
Web
服务:

[[email protected]]# sh menu.sh

1.[install lamp]

2.[install lnmp]

3.[exit]

pls input the num you want:

要求:

1
、当用户输入
1
时,输出“
startinstalling lamp.
”然后执行
/server/scripts/lamp.sh
,脚本内容输出
“lampis installed>”
后退出脚本;

2
、当用户输入
2
时,输出“
startinstalling lnmp.
”然后执行
/server/scripts/lnmp.sh
输出
“lnmpis installed>”
后退出脚本
;

3
、当输入
3
时,退出当前菜单及脚本;

4
、当输入任何其它字符,给出提示“
Input error
”后退出脚本。

5、要对执行的脚本进行相关条件判断,例如:脚本是否存在,是否可执行等。 
>

企业面试题12:

1
、监控
web
服务是否正常,不低于3种监控策略。

2、监控db服务是否正常,不低于3种监控策略。
>
要求间隔1分钟,持续监控。

企业面试题13
:监控
memcache
服务是否正常,模拟用户(
web
客户端)检测。

使用nc命令加上set/get来模拟检测,以及监控响应时间及命中率。
>

企业面试题14

:面试及实战考试题:监控web站点目录(/var/html/www)下所有文件是否被恶意篡改(文件内容被改了),如果有就打印改动的文件名(发邮件),定时任务每3分钟执行一次(10分钟时间完成)。
 

企业面试题15:
企业案例
:
写网络服务独立进程模式下
rsync
的系统启动脚本

例如:/etc/init.d/rsyncd{start|stop|restart} 。
>
要求:
1.要使用系统函数库技巧。
>
2.要用函数,不能一坨SHI的方式。
3.可被chkconfig管理。

企业面试题16:老男孩教育
天津项目学生实践抓阄题目:

好消息,老男孩培训学生外出企业项目实践机会(第6次)来了(本月中旬),但是,名额有限,队员限3人(班长带队)。

因此需要挑选学生,因此需要一个抓阄的程序:

要求:

1、执行脚本后,想去的同学输入英文名字全拼,产生随机数01-99之间的数字,数字越大就去参加项目实践,前面已经抓到的数字,下次不能在出现相同数字。

2、第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出继续等待别的学生输入。
>

企业面试题17:
老男孩
linux
企业面试题:

已知下面的字符串是通过
RANDOM
随机数变量
md5sum|cut-c 1-8
截取后的结果,请破解这些字符串对应的
md5sum
前的
RANDOM
对应数字?

21029299

00205d1c

a3da1677

1f6d12dd

890684b

企业面试题18:
批量检查多个网站地址是否正常 

要求:shell数组方法实现,检测策略尽量模拟用户访问思路

http://www.etiantian.org

http://www.taobao.com

http://oldboy.blog.51cto.com

http://10.0.0.7 

转载的网友,请务必保留全部内容谢谢。

检查标准:

1、查看实现的脚本,并询问脚本中的设计思想及实现流程。

2、必要情况下,面试官可以看着你要求你重新开发出来。

3、检查人:班长,组长,老男孩老师,助教。

原文:http://oldboy.blog.51cto.com/2561410/1632876

shell: linux正则表达式awk讲解

awk和sed一样是流式编辑器,它也是针对文档中的行来操作的,一行一行的去执行。awk比sed更加强大,它能做到sed能做到的,同样也能做到sed不能做到的。awk常用来分段;

awk不用加任何参数就可以实现 + ? * .  | 这些特殊符号;

1、截取文档中的某个段

[[email protected] ~]# head -n2 passwd |awk -F: ‘{print $1}’

root

bin

[[email protected] ~]# head -n2 passwd |awk -F: ‘{print $0}’

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

[[email protected] ~]# head -n2 passwd |awk -F: ‘{print $1,$3,$7}’

root 0 /bin/bash

bin 1 /sbin/nologin

-F 选项的作用是指定分隔符,如果不加-F指定,则以空格或者tab为分隔符。 Print为打印的动作,用来打印出某个字段。$1为第一个字段,$2为第二个字段,依次类推,有一个特殊的那就是$0,它表示整行。

{ }内可以打印多个字段$1,$3,$7 打印第1、3、7段,中间用逗号隔开;

打印分段默认分隔符为空格,可以自定义分隔符,分隔符需要用冒号括起来;也可以OFS定义输出分隔符;

[[email protected] ~]# awk -F: ‘{print $3,$4}’ 1.txt |head -5

[[email protected] ~]# awk -F: ‘{print $3″:>”$4}’ 1.txt |head -5

[[email protected] ~]# awk -F: ‘OFS=”#>”{print $3,$4}’ 1.txt |head -5

[[email protected] ~]# head -n2 passwd |awk -F: ‘{print $1″#>””@>”$3″#>”$7}’

root#@0#/bin/bash

bin#@1#/sbin/nologin

注意awk的格式,-F后紧跟单引号,然后里面为分隔符,print的动作要用 { } 括起来,否则会报错。print还可以打印自定义的内容,但是自定义的内容要用“”双引号括起来。

2、匹配字符或字符串

[[email protected] ~]# awk -F: ‘$1~/me/’ passwd

games:x:12:100:games:/usr/games:/sbin/nologin

[[email protected] ~]# awk -F: ‘$1~/user/’ passwd

user1:x:600:501::/home/user1:/bin/bash

可以让某个段去匹配,~ 表示匹配的意思,以冒号分隔第一字段然后匹配//里的关键字;

[[email protected] ~]# awk -F: ‘/root/ {print $1,$3} /user/ {print $1,$3}’ passwd

root 0

operator 11

ftp 14

saslauth 499

user1 600

awk还可以多次匹配,如上例全文匹配包含root关键词的行,再匹配包含user的行,打印所匹配的第1、3段。

3、条件操作符

判断第3个字段为0的

[[email protected] ~]# awk -F: ‘$3==”0>”‘ passwd

root:x:0:0:root:/root:/bin/bash

[[email protected] ~]# awk -F: ‘$3==10’ passwd

uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

判断第3个字段为10的并且打印该行的第7字段;

[[email protected] ~]# awk -F: ‘$3==10 {print $7}’ passwd

/sbin/nologin

[[email protected] ~]# awk -F: ‘$3==”600>”‘ passwd

user1:x:600:501::/home/user1:/bin/bash

awk中是可以用逻辑符号判断的,比如 ‘==’ 就是等于,也可以理解为 ‘精确匹配’ 另外也有 >, ‘>=, ‘不加双引号则认为是数字。

示例,双引号括起来认为是字符;加单引号和不加则认为是数字;

[[email protected] ~]# awk -F: ‘$3>”500>”‘ passwd | sort -t: -k 3 -n

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin

sshd:x:74:74:privilege-separated ssh:/var/empty/sshd:/sbin/nologin

dbus:x:81:81:system message bus:/:/sbin/nologin

postfix:x:89:89::/var/spool/postfix:/sbin/nologin

nobody:x:99:99:nobody:/:/sbin/nologin

user1:x:600:501::/home/user1:/bin/bash

[[email protected] ~]# awk -F: ‘$3>500’ passwd | sort -t: -k 3 -n

user1:x:600:501::/home/user1:/bin/bash

[[email protected] ~]# awk -F: ‘$3>’500” passwd | sort -t: -k 3 -n

user1:x:600:501::/home/user1:/bin/bash

!= 为不匹配,第7字段不等于/sbin/nologin的行,需要用双引号括起来。

[[email protected] ~]# awk -F: ‘$7!=”/sbin/nologin>”‘ passwd

root:x:0:0:root:/root:/bin/bash

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

user1:x:600:501::/home/user1:/bin/bash

mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash

除了针对某一个段的字符进行逻辑比较外,还可以两个段之间进行逻辑比较。

[[email protected] ~]# awk -F: ‘$3>”5>” && $3

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin

user1:x:600:501::/home/user1:/bin/bash

另外还可以使用 && “并且”和  || “或者” 的意思。

示例,打印第3段大于第4段,并且第7段为/bin/bash的行;

[[email protected] ~]# awk -F: ‘$3>$4 && $7==”/bin/bash>”‘ passwd

user1:x:600:501::/home/user1:/bin/bash

示例,打印第3段小于第4段,或者第7段为/bin/bash的行;

[[email protected] ~]# awk -F: ‘$3

root:x:0:0:root:/root:/bin/bash

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

games:x:12:100:games:/usr/games:/sbin/nologin

gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

ftp:x:14:50:ftp user:/var/ftp:/sbin/nologin

user1:x:600:501::/home/user1:/bin/bash

mysql:x:27:27:mysql server:/var/lib/mysql:/bin/bash


[1]
 [2]  下一页

原文:http://www.myhack58.com/Article/48/66/2015/61268.htm

shell: 【每日一博】Shell 特殊用法续

1.函数中输出函数名: $FUNCNAME

注意该变量是一个数组,如果嵌套调用函数,那么最里层函数中的此变量会是按调用顺序排列的所有函数的数组,如:

function log() {
    echo ${FUNCNAME[@]}
}
function action() {
    log
}
action 

输出内容是:log action

如果只想获得当前函数的名称,直接输出即可: echo $
FUNCNAME

用途:日志函数或者函数名传递等。

参考: Bash 获取当前函数名

2.循环中的跳转: continue [n]

首先需要声明的是continue可用于子函数,跳转到父函数中的指定层次循环。如:

function son() {
	for z in 1 2 3; do
		if true; then
			echo $x,$y,$z
			continue 3
		fi
	done
}
function father() {
	for x in 1 2 3; do
		for y in 1 2 3; do
			son
		done
	done
}
father
 
  • n的值从1开始(不写默认为1,数字越大则层数越高,超过总循环层数时值为最大层数);
  • 以上代码中只有最上层”x>”会正常循环完,其余子层都在首轮跳出,此时n的最大值为3;
  • 若在son后加一个“&”使其在后台运行,此时continue能控制y、z两层,但不能跳转到x,即n的最大值为2。

3.uniq注意事项

Note: ‘uniq’ does not detect repeated lines unless they are adjacent.

该命令容易被忽略的一点是,它只会比较相邻的行而不会跨行比较,除非必要,否则最好先排序:

sort -u

4.变量间接引用(indirect expansion)

两种方法见如下代码:

a=1
b=a
echo ${!b}
eval echo $$b

参考: shell 间接变量引用的问题
Parameter Expansion

5.sed模式空间

以下4种用法,第一个会替换每一行的第一个小写a,第二与第四个则会替换所有小写a,第三个只会替换第一行的第一个小写a:

printf 'aaanaaa' | sed 's/a/A/'
printf 'aaanaaa' | sed 's/a/A/g'
printf 'aaanaaa' | sed ':a;N;$!ba;s/a/A/'
printf 'aaanaaa' | sed ':a;N;$!ba;s/a/A/g' 

但是如果原始数据只有一行,那么最后两种写法均不会生效,

因此最好的写法是只替换第一行的第一个字符: printf ‘aaanaaan’ | sed ‘1s/a/A/’

参考: 让sed只替换一次

6.条件表达式

( ! [[ '123' =~ ^[0-9]+$ || 1 -gt 0 ]] ) && echo 1 || echo 2
( ! [ 1 -eq 2 -o 1 -gt 0 ] ) && echo 1 || echo 2
[ ! 1 -eq 2 -o 1 -gt 0 ] && echo 1 || echo 2
! [ 1 -eq 2 -o 1 -gt 0 ] && echo 1 || echo 2 

注意:

  • 带正则表达式的条件语句必须要写在双中括号“[[]]”中;

注意:在[] 表达式中,常见的>,<需要加转义字符,表示字符串大小比较,以acill码 位置作为比较。 不直接支持<>运算符,还有逻辑运算符|| && 它需要用-a[and] –o[or]表示

注意:[[]] 运算符只是[]运算符的扩充。能够支持<,>符号运算不需要转义符,它还是以字符串比较大小。里面支持逻辑运算符:|| &&

  • 如果要对整个条件语句取反,最好是将“!”写在“[]”之外,并且尽量用“()”包围起来;
  • 以上第三种写法没有达到要求,第四行不推荐,推荐前两种写法;

不考虑对低版本bash和对sh的兼容的情况下,用[[]]是兼容性强,而且性能比较快,在做条件运算时候,可以使用该运算符。

7.to be continued

原文:http://my.oschina.net/cwalet/blog/402756

shell: Linux Shell 学习笔记 一 目录结构

以Red Hat Enterprise Linux 各版本为例,RHEL中目录具体作用如下,

/bin       存放普通用户使用的命令

/sbin     存放管理员可以执行的命令

/home   存放普通用户的家目录 如zhangshan家目录为/zhangshan

/root     管理员的家目录

/etc       存放配置文件的目录

/boot     存放跟启动相关的文件

/usr       用户自定义的相关程序文件

/porc     内核,硬件参数相关的目录

/var       内容经常变化的文件存放目录 如日志

/temp    临时文件的存放目录

/run       存放进程文件的目录  (RHEL7)

Linux Shell  分为外部命令和内部命令,

内部命令:指的是集成于Shell解释器程序(如Bash)内部的一些特殊指令,也成为内建(Built-IN)指令。内部命令属于Shell的一部分,所以并没有单独对应的系统文件,只要Shell解释器被运行,内部指令也就自动载入内存了,用户可以直接使用。内部命令无需从硬盘中重新读取文件,因此执行效率更高。

外部命令:指的是Linux系统中能够完成特定功能的脚本文件或二进制程序,每个外部命令对应了系统中的一个文件,是属于Shell解释器程序之外的命令,所以称为外部命令。Linux系统必须知道外部命令对应的文件位置,才能够由Shell加载并执行。

Linux系统默认会将存放外部命令、程序的目录(如/bin、/usr/bin、/usr/local/bin等)添加到用户的“搜索路径”中,当使用位于这些目录中的外部命令时,用户不需要指定具体的位置。因此在大多数情况下,不用刻意去分辨内部、外部命令,其使用方法是基本类似的。

查看命令的存放位置可以用typer

比如 tar 查询的话用type tar 查看,结果会显示/usr/bin/tar显然这是个外部命令,如果查type cd得到的结果是 cd是shell内嵌,显然是内嵌命令

shell: Linux Shell 学习笔记 一 目录结构
shell: Linux Shell 学习笔记 一 目录结构

通常使用type这个命令用查看命令的所在文件夹,然后再用rpm这个命令查询这个命令安装所对应的软件包,

列入查看renice命令则可以用typer renice,得到的答案在用rpm查询

type renice

rpm -qf /usr/bin/renice

shell: Linux Shell 学习笔记 一 目录结构
shell: Linux Shell 学习笔记 一 目录结构

原文:http://www.cnblogs.com/Frankhu/p/4437346.html

shell: linux shell取变量的子串26种方法实践

##########20150419#########################
#####题目:变量a='a/b/c'如何截取得到c
@@@@@@@@@@@@@@@@来自运维班21期悠久之翼整理@@@@@@@@@@@@@@@@@@@
[[email protected] shell]$ uname -r
2.6.32-504.el6.x86_64
[[email protected] shell]$ cat /etc/redhat-release
CentOS release 6.6 (Final)
方法一
[[email protected] shell]$ echo $a | cut -c5
c
方法二
[[email protected] shell]$ echo $a | tr "a/b/>" "	 >"	 ##四个空格
	 c
方法三
[[email protected] shell]$ echo $a | tr "/>" "n>"|tail -1
c
方法四
[[email protected] shell]$ echo $a | tr -d 'a/b/'
c
方法五
[[email protected] shell]$ echo $a | rev |head -c1
c[[email protected] shell]$
方法六
[[email protected] shell]$ echo $a | rev |cut -c1
c
方法七
[[email protected] shell]$ echo $a | grep -o "[a-z]$>"
c
方法八
[[email protected] shell]$ echo $a | grep -o "[^ab/]>"
c
方法九
[[email protected] shell]$ echo $a | sed  's#.*/##'
c
方法十
 [[email protected] shell]$ echo $a | sed 'y#a/b/#	 #'  ##四个空格
	 c
方法十一
[[email protected] shell]$ echo $a | sed -r 's#....(.)#1#'
c
方法十二
[[email protected] shell]$ echo $a | sed -r 's#.*([a-z]$)#1#'
c
方法十三
[[email protected] shell]$ echo $a | awk -F/ '{print $NF}'
c
方法十四
[[email protected] shell]$ echo $a | awk '{gsub(".*/>",">",$0);print}'
c
方法十五
[[email protected] shell]$ echo $a | awk '{split($0,array,"/>");print array[3]}'
c
方法十六
[[email protected] shell]$ echo $a | awk '{split($0,array,"a/b/>");print array[2]}'
c
方法十七
[[email protected] shell]$ echo $a | awk '{sub(/[^c]+/,">");print}'
c
方法十八
[[email protected] shell]$ echo $a | awk '{gsub("/>","n>");print $3}'
c
方法十九
[[email protected] shell]$ echo $a | awk '{print substr($0,5,1) }'
c
方法二十
[[email protected] shell]$ echo $a | awk  'BEGIN{RS="[/n]>"}NR==3'
c
方法二十一
[[email protected] shell]$ echo $a|cut -d/ -f3	##上海-龚小逸N
c
方法二十二
[[email protected] shell]$ echo ${a:4}			##北京-徐富成
c
方法二十三
[[email protected] shell]$ echo ${a##*/}			##北京-徐富成
c
方法二十四
[[email protected] shell]$ echo $a |tr "/>" "n>"|awk 'NR==3'
c
方法二十五
[[email protected] shell]$ echo ${a:4:1}			##上海-龚小逸
c
方法二十六
[[email protected] shell]$ echo ${a##a/b/}  		##北京-刘晓涛
c
 

原文:http://oldboy.blog.51cto.com/2561410/1636006