标签: shell

  • cronshell 多台服务器相同 crontab 只执行一次

    https://github.com/selboo/cronshell

    cronshell

    多台服务器相同 crontab 只执行一次

    cronshell 安装

    # go build
    

    cronshell 配置

     # cat /etc/cronshell.conf
    [Log]
    logfile=/var/log/cronshell.log
    
    [Redis]
    host=192.168.15.100
    port=6379
    
    • logfile 日志路径
    • host redis 地址
    • port redis 端口

    crontab 配置

    服务器 Server A01

    # cat /etc/cron.d/cronshell
    MAILTO=""
    SHELL=/bin/cronshell
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    
    * * * * * root d=$(date); echo $d run ok >> /tmp/t.log
    

    查看执行结果

    # cat /tmp/t.log
    Sat May 30 22:47:01 CST 2020 run ok
    Sat May 30 22:48:01 CST 2020 run ok
    Sat May 30 22:51:01 CST 2020 run ok
    Sat May 30 22:54:01 CST 2020 run ok
    

    服务器 Server B01

    # cat /etc/cron.d/cronshell
    MAILTO=""
    SHELL=/bin/cronshell
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    
    * * * * * root d=$(date); echo $d run ok >> /tmp/t.log
    

    查看执行结果

    # cat /tmp/t.log
    Sat May 30 22:49:01 CST 2020 run ok
    Sat May 30 22:50:01 CST 2020 run ok
    Sat May 30 22:52:01 CST 2020 run ok
    Sat May 30 22:53:01 CST 2020 run ok
    Sat May 30 22:55:01 CST 2020 run ok
    Sat May 30 22:56:01 CST 2020 run ok
    

    转载请注明:爱开源 » cronshell 多台服务器相同 crontab 只执行一次

  • shellcheck 帮助你写出更好的脚本

    简介

    shellcheck 是一款实用的 shell脚本静态检查工具。

    首先,可以帮助你提前发现并修复简单的语法错误,节约时间。每次都需要运行才发现写错了一个小地方,确实非常浪费时间。
    其次,可以针对你当前不够完善不够健壮的写法,提供建议,帮助你提前绕开一些坑,避免等问题真的发生了才去调试处理。

    在其介绍中,目标是针对所有用户的,从初学者到高手,都用得上

    • 指出并澄清典型的初学者的语法问题,那通常会shell提供神秘的错误消息。
    • 指出并澄清典型的中级的语义问题,这些问题会导致shell出现奇怪且反直觉的行为。
    • 指出可能导致高级用户的脚本中,可能在未来某种情况下失败的陷阱。

    如何使用

    在网页上使用

    非常简单,在网页 https://www.shellcheck.net 上,贴入你的脚本,运行检查即可

    在命令行中使用

    下载后,在命令行中调用 shellcheck yourscript 即可

    集成到编辑器中(推荐)

    推荐将shellcheck直接集成到日常编辑器中,这样就可以直接在编辑器中查看ShellCheck建议,以最快速度发现并修复问题。

    • Vim 通过 ALE, Neomake 或 Syntastic 进行集成
    • Emacs 通过 Flycheck 或 Flymake 集成
    • Sublime 通过 SublimeLinter.
    • Atom 通过 Linter.
    • VSCode 通过 vscode-shellcheck.

    安装方式

    在大多数发行版的包管理中,已经有shellcheck了,如在基于debian的机器上

    apt-get install shellcheck
    

    其他系统的具体安装方式,可以查阅 shellcheck 的github首页介绍

    当然,也可以选择自行从源码安装。

    问题列表

    那么shellcheck具体会检查一些什么问题呢,以下给出一个不完整的问题检查列表。
    可以看下,你是否都能意识到这样的写法时有错误或隐患的。
    如果发现有自己不知道的或自己容易错漏的,那么也许你也应该花点时间,装上shellcheck。

    引号问题

    echo $1                           # Unquoted variables  #变量未加引号
    find . -name *.ogg                # Unquoted find/grep patterns #find/grep 的匹配模式未加引号
    rm "~/my file.txt"                # Quoted tilde expansion #引号中的波浪符扩展
    v='--verbose="true"'; cmd $v      # Literal quotes in variables # 变量中的字面引号
    for f in "*.ogg"                  # Incorrectly quoted 'for' loops # 错误的for循环
    touch $@                          # Unquoted $@  # $@未加引号
    echo 'Don't forget to restart!'   # Singlequote closed by apostrophe  # 单引号被撇号意外关闭了
    echo 'Don\'t try this at home'    # Attempting to escape ' in ''  #试图在单引号括起来的部分中加上一个单引号
    echo 'Path is $PATH'              # Variables in single quotes # 将变量用单引号括起来
    trap "echo Took ${SECONDS}s" 0    # Prematurely expanded trap #过早扩展陷阱
    

    条件判断

    ShellCheck 可以识别大多数不正确的条件判断语句

    [[ n != 0 ]]                      # Constant test expressions  # 常量测试表达式
    [[ -e *.mpg ]]                    # Existence checks of globs # 对文件是否存在进行检查时,使用通配符
    [[ $foo==0 ]]                     # Always true due to missing spaces #由于缺乏空格,结果总是为真
    [[ -n "$foo " ]]                  # Always true due to literals #由于字面值存在,结果总是为真
    [[ $foo =~ "fo+" ]]               # Quoted regex in =~   # 在 =~ 中使用正则表达式
    [ foo =~ re ]                     # Unsupported [ ] operators # 不支持的[]运算符
    [ $1 -eq "shellcheck" ]           # Numerical comparison of strings # 比较数字和字符串
    [ $n && $m ]                      # && in [ .. ]  # 在[]中使用&&运算符
    [ grep -q foo file ]              # Command without $(..)  #命令缺少了$(..)
    [[ "$$file" == *.jpg ]]           # Comparisons that can't succeed #无法成功的比较
    (( 1 -lt 2 ))                     # Using test operators in ((..)) #在((..))中使用比较
    

    常见的对命令的错误使用

    ShellCheck 可以识别对一些命令的错误使用

    grep '*foo*' file                 # Globs in regex contexts  #在grep的正则表达式中前后使用通配符
    find . -exec foo {} && bar {} \;  # Prematurely terminated find -exec  # 使find -exec 过早结束
    sudo echo 'Var=42' > /etc/profile # Redirecting sudo # 重定向sudo
    time --format=%s sleep 10         # Passing time(1) flags to time builtin # 将time(1)的标志传递给内建的time
    while read h; do ssh "$h" uptime  # Commands eating while loop input  # 一个获取输入的while循环中,使用同样会获取输入的命令
    alias archive='mv $1 /backup'     # Defining aliases with arguments # 定义使用参数的alias
    tr -cd '[a-zA-Z0-9]'              # [] around ranges in tr # 在tr的参数范围外使用[]
    exec foo; echo "Done!"            # Misused 'exec'  # 错误地使用exec
    find -name \*.bak -o -name \*~ -delete  # Implicit precedence in find  # 在find中的隐式优先级
    # find . -exec foo > bar \;       # Redirections in find  #find中的重定向
    f() { whoami; }; sudo f           # External use of internal functions #在外部使用内部函数
    

    初学者的常见错误

    ShellCheck 识别很多初学者的语法错误

    var = 42                          # Spaces around = in assignments #等号两边的空格
    $foo=42                           # $ in assignments # 对变量赋值时使用了$
    for $var in *; do ...             # $ in for loop variables  # 在循环变量处使用$
    var$n="Hello"                     # Wrong indirect assignment #错误的变量
    echo ${var$n}                     # Wrong indirect reference #错误的引用
    var=(1, 2, 3)                     # Comma separated arrays #逗号分割数组
    array=( [index] = value )         # Incorrect index initialization #错误的索引初始化
    echo $var[14]                     # Missing {} in array references #引用数组缺少{}
    echo "Argument 10 is $10"         # Positional parameter misreference #错误的位置参数引用
    if $(myfunction); then ..; fi     # Wrapping commands in $() #在命令外加上$()
    else if othercondition; then ..   # Using 'else if'  #使用else if
    f; f() { echo "hello world; }     # Using function before definition 在函数定义之前使用函数
    [ false ]                         # 'false' being true # 此处false为true
    if ( -f file )                    # Using (..) instead of test #使用()取代测试条件
    

    风格

    ShellCheck 可以提出一些风格改进建议

    [[ -z $(find /tmp | grep mpg) ]]  # Use grep -q instead  #改成使用grep -q
    a >> log; b >> log; c >> log      # Use a redirection block instead #改成使用重定向块
    echo "The time is `date`"         # Use $() instead #改成使用$()
    cd dir; process *; cd ..;         # Use subshells instead   #改成使用subshell
    echo $[1+2]                       # Use standard $((..)) instead of old $[]  #改成使用标准的$((..))
    echo $(($RANDOM % 6))             # Don't use $ on variables in $((..)) #在$((..))中不要使用$
    echo "$(date)"                    # Useless use of echo # 没必要的echo
    cat file | grep foo               # Useless use of cat #没必要的cat
    

    数据和拼写错误

    ShellCheck 可以识别一些数据和拼写错误

    args="$@"                         # Assigning arrays to strings # 将数组赋值给字符串
    files=(foo bar); echo "$files"    # Referencing arrays as strings # 把数字当成字符串引用
    declare -A arr=(foo bar)          # Associative arrays without index # 不带索引组合数组
    printf "%s\n" "Arguments: $@."    # Concatenating strings and arrays # 连接字符串和数组
    [[ $# > 2 ]]                      # Comparing numbers as strings # 把数字当成字符串比较
    var=World; echo "Hello " var      # Unused lowercase variables # 未使用的小写变量
    echo "Hello $name"                # Unassigned lowercase variables # 未赋值的小写变量
    cmd | read bar; echo $bar         # Assignments in subshells # 在subshells中进行赋值
    cat foo | cp bar                  # Piping to commands that don't read # 通过管道传递数据给一个不会做读取的程序
    printf '%s: %s\n' foo             # Mismatches in printf argument count # pirintf参数数量不匹配
    

    鲁棒性

    ShellCheck可以做出一些增强脚本鲁棒性的建议

    rm -rf "$STEAMROOT/"*            # Catastrophic rm # 可能导致灾难性后果的rm
    touch ./-l; ls *                 # Globs that could become options # 使用了可能变成选项的通配符
    find . -exec sh -c 'a && b {}' \; # Find -exec shell injection # Find -exec shell注入
    printf "Hello $name"             # Variables in printf format # 在printf的格式化参数中使用变量
    for f in $(ls *.txt); do         # Iterating over ls output # 在ls的输出上进行迭代
    export MYVAR=$(cmd)              # Masked exit codes # 使退出码模糊
    case $version in 2.*) :;; 2.6.*) # Shadowed case branches # 隐蔽的case分支
    

    可移植性

    ShellCheck 警告你使用了 shebang 不支持的特性.。
    比如,当你设置 shebang 为 #!/bin/sh 是, ShellCheck 对类似 checkbashisms 的可移植性问题发出警告。

    echo {1..$n}                     # Works in ksh, but not bash/dash/sh    #在 ksh 中可用,在 bash/dash/sh 中不可用
    echo {1..10}                     # Works in ksh and bash, but not dash/sh #在 ksh 中可用,在 bash/dash/sh 中不可用
    echo -n 42                       # Works in ksh, bash and dash, undefined in sh #在 ksh/bash/dash 中可用,在 sh 中不可用
    trap 'exit 42' sigint            # Unportable signal spec # 不具有可移植性的信号细节
    cmd &> file                      # Unportable redirection operator # 不具有可移植性的重定向操作
    read foo < /dev/tcp/host/22      # Unportable intercepted files  # 不具有可移植性的截获的文件
    foo-bar() { ..; }                # Undefined/unsupported function name # 未定义/不支持的函数名
    [ $UID = 0 ]                     # Variable undefined in dash/sh # dash/sh 中未定义的变量
    local var=value                  # local is undefined in sh # sh 中未定义local
    time sleep 1 | sleep 5           # Undefined uses of 'time' # 使用了time未定义的用法
    

    其他杂七杂八的问题

    ShellCheck 可以识别到一些其他问题

    PS1='\e[0;32m\$\e[0m '            # PS1 colors not in \[..\]  # PS1 的颜色不在\[..\] 中
    PATH="$PATH:~/bin"                # Literal tilde in $PATH # $PATH中的波浪号
    rm “file”                         # Unicode quotes #Unicode 引号
    echo "Hello world"                # Carriage return / DOS line endings # 传输返回DOS行结束符/
    echo hello \                      # Trailing spaces after \   # \后面的行尾空格
    var=42 echo $var                  # Expansion of inlined environment # 展开内联环境变量
    #!/bin/bash -x -e                 # Common shebang errors # shebang  命令错误
    echo $((n/180*100))               # Unnecessary loss of precision # 不必要的精度丢失
    ls *[:digit:].txt                 # Bad character class globs # 不好的通配符
    sed 's/foo/bar/' file > file      # Redirecting to input # 重定向到输入
    while getopts "a" f; do case $f in "b") # Unhandled getopts flags # 未处理的getopts标志
    

    总结

    以上就是shellcheck的介绍了,主要来自其github 的readme ,源码在 githubhttps://github.comf/koalaman/shellcheck

    简单实用,只要配置好了,就可以持续为你提供帮助。而且这个是建议性的,可以自己根据实际情况决定是否采纳。即用即弃的临时脚本,那兼容性等就不用太care。长期使用的,就还是完善一下比较稳妥。

    转载请注明:爱开源 » shellcheck 帮助你写出更好的脚本

  • tmux快捷键

    Ctrl+b 激活控制台;此时以下按键生效
    系统操作 ? 列出所有快捷键;按q返回
    d 脱离当前会话;这样可以暂时返回Shell界面,输入tmux attach能够重新进入之前的会话
    D 选择要脱离的会话;在同时开启了多个会话时使用
    Ctrl+z 挂起当前会话
    r 强制重绘未脱离的会话
    s 选择并切换会话;在同时开启了多个会话时使用
    : 进入命令行模式;此时可以输入支持的命令,例如kill-server可以关闭服务器
    [ 进入复制模式;此时的操作与vi/emacs相同,按q/Esc退出
    ~ 列出提示信息缓存;其中包含了之前tmux返回的各种提示信息
    窗口操作 c 创建新窗口
    & 关闭当前窗口
    数字键 切换至指定窗口
    p 切换至上一窗口
    n 切换至下一窗口
    l 在前后两个窗口间互相切换
    w 通过窗口列表切换窗口
    , 重命名当前窗口;这样便于识别
    . 修改当前窗口编号;相当于窗口重新排序
    f 在所有窗口中查找指定文本
    面板操作 将当前面板平分为上下两块
    % 将当前面板平分为左右两块
    x 关闭当前面板
    ! 将当前面板置于新窗口;即新建一个窗口,其中仅包含当前面板
    Ctrl+方向键 以1个单元格为单位移动边缘以调整当前面板大小
    Alt+方向键 以5个单元格为单位移动边缘以调整当前面板大小
    Space 在预置的面板布局中循环切换;依次包括even-horizontal、even-vertical、main-horizontal、main-vertical、tiled
    q 显示面板编号
    o 在当前窗口中选择下一面板
    方向键 移动光标以选择面板
    { 向前置换当前面板
    } 向后置换当前面板
    Alt+o 逆时针旋转当前窗口的面板
    Ctrl+o 顺时针旋转当前窗口的面板

    相关文章

    转载请注明:爱开源 » tmux快捷键

  • Linux中find常见用法示范以及删除7天前的文件

    Linux中find常见用法示例以及删除7天前的文件
    ·find path -option [ -print ] [ -exec -ok command ] {} \;

    find命令的参数;

    pathname: find命令所查找的目录路径。例如用.来表示当前目录,用/来表示系统根目录。
    -print: find命令将匹配的文件输出到标准输出。
    -exec: find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为’command’ { } \;,注意{ }和\;之间的空格。
    -ok: 和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。

    #-print 将查找到的文件输出到标准输出
    #-exec command {} \; —–将查到的文件执行command操作,{} 和 \;之间有空格
    #-ok 和-exec相同,只不过在操作前要询用户
    例:find . -name .svn | xargs rm -rf
    ====================================================
    -name filename #查找名为filename的文件
    -perm #按执行权限来查找
    –user username #按文件属主来查找
    -group groupname #按组来查找
    -mtime -n +n #按文件更改时间来查找文件,-n指n天以内,+n指n天以前
    -atime -n +n #按文件访问时间来查GIN: 0px”>

    -ctime -n +n #按文件创建时间来查找文件,-n指n天以内,+n指n天以前

    -nogroup #查无有效属组的文件,即文件的属组在/etc/groups中不存在
    -nouser #查无有效属主的文件,即文件的属主在/etc/passwd中不存
    -newer f1 !f2 找文件,-n指n天以内,+n指n天以前
    -ctime -n +n #按文件创建时间来查找文件,-n指n天以内,+n指n天以前
    -nogroup #查无有效属组的文件,即文件的属组在/etc/groups中不存在
    -nouser #查无有效属主的文件,即文件的属主在/etc/passwd中不存
    -newer f1 !f2 #查更改时间比f1新但比f2旧的文件
    -type b/d/c/p/l/f #查是块设备、目录、字符设备、管道、符号链接、普通文件
    -size n[c] #查长度为n块[或n字节]的文件
    -depth #使查找在进入子目录前先行查找完本目录
    -fstype #查更改时间比f1新但比f2旧的文件
    -type b/d/c/p/l/f #查是块设备、目录、字符设备、管道、符号链接、普通文件
    -size n[c] #查长度为n块[或n字节]的文件
    -depth #使查找在进入子目录前先行查找完本目录
    -fstype #查位于某一类型文件系统中的文件,这些文件系统类型通常可 在/etc/fstab中找到
    -mount #查文件时不跨越文件系统mount点
    -follow #如果遇到符号链接文件,就跟踪链接所指的文件
    -cpio %; #查位于某一类型文件系统中的文件,这些文件系统类型通常可 在/etc/fstab中找到
    -mount #查文件时不跨越文件系统mount点
    -follow #如果遇到符号链接文件,就跟踪链接所指的文件
    -cpio #对匹配的文件使用cpio命令,将他们备份到磁带设备中
    -prune #忽略某个目录
    =====================================================
    $find ~ -name “.txt” -print #在$HOME中查.txt文件并显示
    $find . -name “
    .txt” -print
    $find . -name “[A-Z]” -print #查以大写字母开头的文件
    $find /etc -name “host
    ” -print #查以host开头的文件
    $find . -name “[a-z][a-z][0–9][0–9].txt” -print #查以两个小写字母和两个数字开头的txt文件
    $find . -perm 755 -print
    $find . -perm -007 -exec ls -l {} \; #查所有用户都可读写执行的文件同-perm 777
    $find . -type d -print
    $find . ! -type d -print
    $find . -type l -print

    $find . -size +1000000c -print #查长度大于1Mb的文件
    $find . -size 100c -print # 查长度为100c的文件
    $find . -size +10 -print #查长度超过期作废10块的文件(1块=512字节)

    $cd /
    $find etc home apps -depth -print | cpio -ivcdC65536 -o /dev/rmt0
    $find /etc -name “passwd” -exec grep “cnscn” {} \; #看是否存在cnscn用户
    $find . -name “yao
    ” | xargs file
    $find . -name “yao” | xargs echo “” > /tmp/core.log
    $find . -name “yao
    ” | xargs chmod o-w

    ======================================================

    find -name april 在当前目录下查找以april开始的文件
    find -name april
    fprint file 在当前目录下查找以april开始的文件,并把结果输出到file中
    find -name ap -o -name may 查找以ap或may开头的文件
    find /mnt -name tom.txt -ftype vfat 在/mnt下查找名称为tom.txt且文件系统类型为vfat的文件
    find /mnt -name t.txt ! -ftype vfat 在/mnt下查找名称为tom.txt且文件系统类型不为vfat的文件
    find /tmp -name wa* -type l 在/tmp下查找名为wa开头且类型为符号链接的文件
    find /home -mtime -2 在/home下查最近两天内改动过的文件
    find /home -atime -1 查1天之内被存取过的文件
    find /home -mmin +60 在/home下查60分钟前改动过的文件
    find /home -amin +30 查最近30分钟前被存取过的文件
    find /home -newer tmp.txt 在/home下查更新时间比tmp.txt近的文件或目录
    find /home -anewer tmp.txt 在/home下查存取时间比tmp.txt近的文件或目录
    find /home -used -2 列出文件或目录被改动过之后,在2日内被存取过的文件或目录
    find /home –user cnscn 列出/home目录内属于用户cnscn的文件或目录
    find /home -uid +501 列出/home目录内用户的识别码大于501的文件或目录
    find /home -group cnscn 列出/home内组为cnscn的文件或目录
    find /home -gid 501 列出/home内组id为501的文件或目录
    find /home -nouser 列出/home内不属于本地用户的文件或目录
    find /home -nogroup 列出/home内不属于本地组的文件或目录
    find /home -name tmp.txt -maxdepth 4 列出/home内的tmp.txt 查时深度最多为3层
    find /home -name tmp.txt -mindepth 3 从第2层开始查
    find /home -empty 查找大小为0的文件或空目录
    find /home -size +512k 查大于512k的文件
    find /home -size -512k 查小于512k的文件
    find /home -links +2 查硬连接数大于2的文件或目录
    find /home -perm 0700 查权限为700的文件或目录
    find /tmp -name tmp.txt -exec cat {} \;
    find /tmp -name tmp.txt -ok rm {} \;

    find / -amin -10 # 查找在系统中最后10分钟访问的文件
    find / -atime -2 # 查找在系统中最后48小时访问的文件
    find / -empty # 查找在系统中为空的文件或者文件夹
    find / -group cat # 查找在系统中属于 groupcat的文件
    find / -mmin -5 # 查找在系统中最后5分钟里修改过的文件
    find / -mtime -1 #查找在系统中最后24小时里修改过的文件
    find / -nouser #查找在系统中属于作废用户的文件
    find / –user fred #查找在系统中属于FRED这个用户的文件
    =============================================================================
    在/ l o g s目录中查找更改时间在7日以前的文件并删除它们:
    $ find logs/ -type f -mtime +7 -exec rm -f {} \;
    在/ l o g s目录中查找更改时间在7日以内的文件并删除它们:
    $ find logs/ -type f -mtime -7 -exec rm -f {} \;
    然后加入的计划任务中每日执行便可

    相关文章

    转载请注明:爱开源 » Linux中find常见用法示范以及删除7天前的文件

  • Linux shell 中的换行符是什么?

    Check File and Folder:

    /code/web/upload/

    /usr/bin/inotifywait

    /usr/bin/rsync

    echo –e “Check File and Folder: \n \t/code/web/upload/ \n \t/usr/bin/inotifywait \n \t/usr/bin/rsync”

    相关文章

    转载请注明:爱开源 » Linux shell 中的换行符是什么?

  • sed 命令详解

    概述

    sed是stream editor的简称,也就是流编辑器。它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”pattern space,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。
    使用语法

    sed命令的使用规则是这样的:
    sed [option] ‘command’ input_file

    其中option是可选的,常用的option有如下几种:
    -n 使用

    安静silent

    模式(想不通为什么不是-s)。在一般sed的用法中,所有来自stdin的内容一般都会被列出到屏幕上。但如果加上-n参数后,则只有经过sed特殊处理的那一行(或者动作)才会被列出来;

    -e 直接在指令列模式上进行 sed 的动作编辑;

    -f 直接将 sed 的动作写在一个文件内, -f filename 则可以执行filename内的sed命令;

    -r 让sed命令支持扩展的正则表达式(默认是基础正则表达式);

    -i 直接修改读取的文件内容,而不是由屏幕输出。
    常用的命令有以下几种:
    a \:追加行append, a \的后面跟上字符串s(多行字符串可以用\n分隔),则会在当前选择的行的后面都加上字符串s;
    c \:

    取代/替换行change

    ,c \后面跟上字符串s(多行字符串可以用\n分隔),则会将当前选中的行替换成字符串s;

    i \:

    插入行insert

    ,i \后面跟上字符串s(多行字符串可以用\n分隔),则会在当前选中的行的前面都插入字符串s;

    d:

    删除行delete

    ,该命令会将当前选中的行删除;

    p:

    打印print

    ,该命令会打印当前选择的行到屏幕上;

    s:

    替换字符串subs

    ,通常s命令的用法是这样的:1,2s/old/new/g,将old字符串替换成new字符串

    命令示例

    假设有一个本地文件test.txt,文件内容如下:
    [qifuguang@winwill~]$ cat test.txt

    this is first line

    this is second line

    this is third line

    this is fourth line

    this fifth line

    happy everyday

    end

    本节将使用该文件详细演示每一个命令的用法。
    a命令(追加行)

    例一

    [qifuguang@winwill~]$ sed ‘1a \add one’ test.txt

    this is first line

    add one

    this is second line

    this is third line

    this is fourth line

    this is fifth line

    happy everyday

    end

    本例命令部分中的1表示第一行,同样的第二行写成2,第一行到第三行写成1,3,用$表示最后一行,比如2,$表示第二行到最后一行中间所有的行(包含第二行和最后一行)。
    本例的作用是在第一行之后增加字符串”add one”,从输出可以看到具体效果。
    例二

    [qifuguang@winwill~]$ sed ‘1,$a \add one’ test.txt

    this is first line

    add one

    this is second line

    add one

    this is third line

    add one

    this is fourth line

    add one

    this is fifth line

    add one

    happy everyday

    add one

    end

    add one

    本例表示在第一行和最后一行所有的行后面都加上”add one”字符串,从输出可以看到效果。
    例三

    [qifuguang@winwill~]$ sed ‘/first/a \add one’ test.txt

    this is first line

    add one

    this is second line

    this is third line

    this is fourth line

    this is fifth line

    happy everyday

    end

    本例表示在包含”first”字符串的行的后面加上字符串”add one”,从输出可以看到第一行包含first,所以第一行之后增加了”add one”
    例四

    [qifuguang@winwill~]$ sed ‘/^ha.*day$/a \add one’ test.txt

    this is first line

    this is second line

    this is third line

    this is fourth line

    this is fifth line

    happy everyday

    add one

    end

    本例使用正则表达式匹配行,^ha.*day$表示以ha开头,以day结尾的行,则可以匹配到文件的”happy everyday”这样,所以在该行后面增加了”add one”字符串。
    i命令(插入行)

    i命令使用方法和a命令一样的,只不过是在匹配的行的前面插入字符串,所以直接将上面a命令的示例的a替换成i即可,在此就不啰嗦了。
    c命令(替换行)

    例五

    [qifuguang@winwill~]$ sed ‘$c \add one’ test.txt

    this is first line

    this is second line

    this is third line

    this is fourth line

    this is fifth line

    happy everyday

    add one

    本例表示将最后一行替换成字符串”add one”,从输出可以看到效果。
    例六

    [qifuguang@winwill~]$ sed ‘4,$c \add one’ test.txt

    this is first line

    this is second line

    this is third line

    add one

    本例将第四行到最后一行的内容替换成字符串”add one”。
    例七

    [qifuguang@winwill~]$ sed ‘/^ha.*day$/c \replace line’ test.txt

    this is first line

    this is second line

    this is third line

    this is fourth line

    this is fifth line

    replace line

    end

    本例将以ha开头,以day结尾的行替换成”replace line”。
    d命令(删除行)

    例八

    [qifuguang@winwill~]$ sed ‘/^ha.*day$/d’ test.txt

    this is first line

    this is second line

    this is third line

    this is fourth line

    this is fifth line

    end

    本例删除以ha开头,以day结尾的行。
    例九

    [qifuguang@winwill~]$ sed ‘4,$d’ test.txt

    this is first line

    this is second line

    this is third line

    本例删除第四行到最后一行中的内容。
    p命令(打印行)

    例十

    [qifuguang@winwill~]$ sed -n ‘4,$p’ test.txt

    this is fourth line

    this is fifth line

    happy everyday

    end

    本例在屏幕上打印第四行到最后一行的内容,p命令一般和-n选项一起使用。
    例十一

    [qifuguang@winwill~]$ sed -n ‘/^ha.*day$/p’ test.txt

    happy everyday

    本例打印以ha开始,以day结尾的行。
    s命令(替换字符串)

    实际运用中s命令式最常使用到的。
    例十二

    [qifuguang@winwill~]$ sed ‘s/line/text/g’ test.txt

    this is first text

    this is second text

    this is third text

    this is fourth text

    this is fifth text

    happy everyday

    end

    本例将文件中的所有line替换成text,最后的g是global的意思,也就是全局替换,如果不加g,则只会替换本行的第一个line。
    例十三

    [qifuguang@winwill~]$ sed ‘/^ha.*day$/s/happy/very happy/g’ test.txt

    this is first line

    this is second line

    this is third line

    this is fourth line

    this is fifth line

    very happy everyday

    end

    本例首先匹配以ha开始,以day结尾的行,本例中匹配到的行是”happy everyday”这样,然后再将该行中的happy替换成very happy。
    例十四

    [qifuguang@winwill~]$ sed ‘s/(.*)line$/\1/g’ test.txt

    this is first

    this is second

    this is third

    this is fourth

    this is fifth

    happy everyday

    end

    这个例子有点复杂,先分解一下。首先s命令的模式是s/old/new/g这样的,所以本例的old部分即(.)line$,sed命令中使用()包裹的内容表示正则表达式的第n部分,序号从1开始计算,本例中只有一个()所以(.)表示正则表达式的第一部分,这部分匹配任意字符串,所以(.)line$匹配的就是以line结尾的任何行。然后将匹配到的行替换成正则表达式的第一部分(本例中相当于删除line部分),使用\1表示匹配到的第一部分,同样\2表示第二部分,\3表示第三部分,可以依次这样引用。比如下面的例子:
    [qifuguang@winwill~]$ sed ‘s/(.
    )is(.*)line/\1\2/g’ test.txt

    this first

    this second

    this third

    this fourth

    this fifth

    happy everyday

    end

    正则表达式中is两边的部分可以用\1和\2表示,该例子的作用其实就是删除中间部分的is。

    转载请注明:爱开源 » sed 命令详解

  • linux bash shell之declare

    declaretypeset内建命令(它们是完全相同的)可以用来限定变量的属性.这是在某些编程语言中使用的定义类型不严格的方式。命令declare是bash版本2之后才有的。命令typeset也可以在ksh脚本中运行。

    declare/typeset 选项

    -r 只读

    declare -r var1
    

    这大致和C的const限定词相同.一个试图改变只读变量值的操作将会引起错误信息而失败. -i 整数

    declare -i number
    # 脚本余下的部分会把"number"当作整数看待.
    
    number=3
    echo "Number = $number"     # Number = 3
    
    number=three
    echo "Number = $number"     # Number = 0
    # 脚本尝试把字符串"three"作为整数来求值(译者注:当然会失败,所以出现值为0).
    

    某些算术计算允许在被声明为整数的变量中完成,而不需要特别使用expr或let来完成。

    n=6/3
    echo "n = $n"       # n = 6/3
    
    declare -i n
    n=6/3
    echo "n = $n"       # n = 2
    

    -a 数组

    declare -a indices
    

    变量indices会被当作数组.

    -f 函数

    declare -f
    

    在脚本中没有带任何参数的declare -f 会列出所有在此脚本前面已定义的函数出来。

    declare -f function_name
    

    declare -f function_name则只会列出指定的函数

    -x export

    declare -x var3
    

    这样将声明一个变量作为脚本的环境变量而被导出。

    -x var=$value

    declare -x var3=373
    

    declare命令允许在声明变量类型的时候同时给变量赋值。


    例子 9-21. 用declare来声明变量类型****

    #!/bin/bash
    
    func1 ()
    {
    echo This is a function.
    }
    
    declare -f        # 列出上面的函数.
    
    echo
    
    declare -i var1   # var1是一个整数.
    var1=2367
    echo "var1 declared as $var1"
    var1=var1+1       # 整数声明后,不需要使用'let'.
    echo "var1 incremented by 1 is $var1."
    # 试图将已声明为整数的变量的值更改为浮点值.
    echo "Attempting to change var1 to floating point value, 2367.1."
    var1=2367.1       # 引起一个错误信息,此变量的值保持原样.
    echo "var1 is still $var1"
    
    echo
    
    declare -r var2=13.36         # 'declare'允许设置变量的属性,
                                  #+ 同时也给变量赋值.
    echo "var2 declared as $var2" # 试图更改只读变量的值.
    var2=13.37                    # 引起错误,并且从脚本退出.
    
    echo "var2 is still $var2"    # 这行不会被执行.
    
    exit 0                        # 脚本不会从这儿退出.
    

    使用内建的declare来限定变量的范围.

    foo ()
    {
    FOO="bar"
    }
    
    bar ()
    {
    foo
    echo $FOO
    }
    
    bar   # 打印 bar.
    

    然而 . . .

    foo (){
    declare FOO="bar"
    }
    
    bar ()
    {
    foo
    echo $FOO
    }
    
    bar  # 什么也不打印.
    
    # 多谢Michael Iatrou指出这一点.
    

    相关文章

    转载请注明:爱开源 » linux bash shell之declare

  • Linux的五个查找命令

    最近,我在学习Linux,下面是一些笔记。

    使用电脑的时候,经常需要查找文件。

    在Linux中,有很多方法可以做到这一点。国外网站LinuxHaxor总结了五条命令,你可以看看自己知道几条。大多数程序员,可能经常使用其中的2到3条,对这5条命令都很熟悉的人应该是不多的。

    aaa

    1. find

    find是最常见和最强大的查找命令,你可以用它找到任何你想找的文件。

    find的使用格式如下:

    $ find <指定目录> <指定条件> <指定动作>

    – <指定目录>: 所要搜索的目录及其所有子目录。默认为当前目录。

    – <指定条件>: 所要搜索的文件的特征。

    – <指定动作>: 对搜索结果进行特定的处理。

    如果什么参数也不加,find默认搜索当前目录及其子目录,并且不过滤任何结果(也就是返回所有文件),将它们全都显示在屏幕上。

    find的使用实例:

    $ find . -name ‘my*’

    搜索当前目录(含子目录,以下同)中,所有文件名以my开头的文件。

    $ find . -name ‘my*’ -ls

    搜索当前目录中,所有文件名以my开头的文件,并显示它们的详细信息。

    $ find . -type f -mmin -10

    搜索当前目录中,所有过去10分钟中更新过的普通文件。如果不加-type f参数,则搜索普通文件+特殊文件+目录。

    a13

    2. locate

    locate命令其实是”find -name”的另一种写法,但是要比后者快得多,原因在于它不搜索具体目录,而是搜索一个数据库(/var/lib/locatedb),这个数据库中含有本地所有文件信息。Linux系统自动创建这个数据库,并且每天自动更新一次,所以使用locate命令查不到最新变动过的文件。为了避免这种情况,可以在使用locate之前,先使用updatedb命令,手动更新数据库。

    locate命令的使用实例:

    $ locate /etc/sh

    搜索etc目录下所有以sh开头的文件。

    $ locate ~/m

    搜索用户主目录下,所有以m开头的文件。

    $ locate -i ~/m

    搜索用户主目录下,所有以m开头的文件,并且忽略大小写。

    a23

    3. whereis

    whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s)。如果省略参数,则返回所有信息。

    whereis命令的使用实例:

    $ whereis grep

    a31

    4. which

    which命令的作用是,在PATH变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果。也就是说,使用which命令,就可以看到某个系统命令是否存在,以及执行的到底是哪一个位置的命令。

    which命令的使用实例:

    $ which grep

    a41

    5. type

    type命令其实不能算查找命令,它是用来区分某个命令到底是由shell自带的,还是由shell外部的独立二进制文件提供的。如果一个命令是外部命令,那么使用-p参数,会显示该命令的路径,相当于which命令。

    type命令的使用实例:

    $ type cd

    系统会提示,cd是shell的自带命令(build-in)。

    $ type grep

    系统会提示,grep是一个外部命令,并显示该命令的路径。

    $ type -p grep

    加上-p参数后,就相当于which命令。

    a51

    转载请注明:爱开源 » Linux的五个查找命令

  • 推荐几本 Unix/Linux 经典书

    几天前答应过一位新 VPS 客户,推荐一点 Linux 书,今天静下来写文才发现推荐书其实不是这么容易,至少应该知道一点读书人的背景,是入门、进阶还是高级,阅读习惯啊、方式啊;有人喜欢看例子书,边看边操作学得快;有的人喜欢先读原理,后操作。

    现在每年增加的信息量比过去几百年还要多,不过好书还是那么少,经过历史考验的经典书就更少了,每个领域的经典书就那么几本,作为初学者应该首先看完该领域的经典书,然后再看其他的流行好书。

    选择经典书是因为,这个拇指就能陌陌的年代我们实在没有时间花在烂书上,好书能更快更好的帮助我们理解内容,好书是一种享受,你不会觉得读书是一种辛苦。选择英文书是因为,这些经典书的英文都写得朴实、简单,不超过大学四级的阅读水平,长时间侵淫英文书可以为自己以后学习和工作打好基础。在工作中,最新最好最权威的资料都是英文的,翻译过来的二手资料不放心,做技术这行迟早要用英语混日子,老板想派你出国培训、开会你不能腼腆的把机会让给别人吧~

    下面是 vpsee 看过的一些好书,有些书至今还放在桌头翻阅,这些经典不管怎么过分推荐和转载都不过分。

    Linux 入门

    Running LinuxLinux in a Nutshell 都是很棒的 Linux 入门书,如果你是计算机专业出身,只需要这两本书就可以了,这两本书都包括一些初级系统管理内容,Linux in a Nutshell 稍微难一点,建议阅读顺序是先 Running Linux 后 Linux in a Nutshell.

    系统管理和网络

    UNIX System Administration Handbook 可能是系统管理方面最权威的的一本大部头百科全书式著作,第一版本是1989年发行的,以后一直是 Unix 系统管理的方面的经典,其作者在2002年发布了对应的 Linux Administration Handbook 第一版,然后又成了 Linux 系统管理的必读,终于在2010年的时候作者把这两本书合为一本 UNIX and Linux System Administration Handbook.

    Essential System Administration 是另一个 Unix/Linux 系统管理的经典书,可以替代 UNIX and Linux System Administration Handbook,不过建议两本都看看。

    TCP/IP Illustrated, Volume 1: The Protocols 是理解 TCP/IP 协议的必读经典,书的内容不涉及具体的网络管理命令,也不讨论如何架设各种服务器,主要讨论 TCP/IP 各层协议是如何工作的,不管你是 System Administrator, Network Administrator, DevOps 还是 System Programmer 这本书都必读,就算今天用 Django, Ruby on Rails 之类的框架编程也应该了解一下底层 HTTP 协议是如何工作的,网络包是如何一层一层的封装、解封的。TCP/IP Illustrated 三部曲的另外两本也很经典,不过太窄太具体,除非你是 TCP/IP 协议设计者或网络栈码农,看 TCP/IP Illustrated, Volume 2: The Implementation 的用处不是很大。

    系统编程

    The UNIX Programming Environment 是两位 UNIX 大师 Brian W. Kernighan 和 Rob Pike 的合著,UNIX/Linux 编程入门的最好读物,字里行间里浸透了 UNIX 的哲学和设计思想。

    The C Programming Language 可能有人会问为啥学 Unix/Linux 要懂 C 语言,C 是 Unix/Linux 的核心,想继续深入理解 Unix/Linux 必须懂点 C 语言,不然下面一些书没法继续读,C 语言还是一种优美、高效的语言,每个程序员都应该会(个人观点)。

    Advanced Programming in the Unix Environment 是 Unix/Linux 编程的经典必读书,Unix 大师级作者 Richard Stevens 的巨著,事实上 Richard Stevens 的每本书都是巨著。

    Unix Network Programming 是 Richard Stevens 另一巨著,这本经典 Unix 网络编程书可看作上面那本的补充。

    编程还应该包括 shell 编程,这里没有单独拿出来推荐是因为因为上面推荐的入门和系统管理书里面都或多或少包括了一些 shell 编程基础知识。

    操作系统原理和内核

    Operating Systems: Design and Implementation 是操作系统原理的经典书,讲系统原理的还有另一本经典恐龙书 Operating System Concepts,我个人更喜欢前一本一些,理论加实践,书的作者在大学教书的时候没能找到满意的操作系统来教学自己写了一个 Minix,Linus Torvalds 发现 Minix 太简单不实用自己写了一个 Linux,貌似牛人都有共同的特点,不满意就自己造一个~,修改 Minix 内核是很有趣的事情,换工作后一直没机会再玩 Minix.

    Linux Device Drivers 是内核编程的入门读物,难得这本经典书还是免费的。

    Understanding the Linux Kernel 是 Linux 内核方面的经典,看这本书之前最好看过一些上面讲操作系统原理的书,不要指望看一遍就把这本书都搞懂,理解内核难点的地方在于内核之间的子系统是独立又是交叉的,又缺少实际可运行可修改的例子,不像 web 编程,改几行代码就可以立刻看到效果,所以内核学习是个痛苦的过程,这本书有助于建立一幅完整的 Linux 内核图景。

    转载请注明:爱开源 » 推荐几本 Unix/Linux 经典书

  • linux bash判断文件或文件夹是否存在

    在写shell脚本的时候,还是有些注意事项的,比如。。空格,给变量赋值不能有空格,象a=1就不能写成a = 1,刚开始的时候好纠结。。

    写判断语句的时候[]之间一定要有空格。以下是一些常见的判断:

    #shell判断文件夹是否存在
    
    #如果文件夹不存在,创建文件夹
    if [ ! -d "/myfolder" ]; then
      mkdir /myfolder
    fi
    
    #shell判断文件,目录是否存在或者具有权限
    
    folder="/var/www/"
    file="/var/www/log"
    
    # -x 参数判断 $folder 是否存在并且是否具有可执行权限
    if [ ! -x "$folder"]; then
      mkdir "$folder"
    fi
    
    # -d 参数判断 $folder 是否存在
    if [ ! -d "$folder"]; then
      mkdir "$folder"
    fi
    
    # -f 参数判断 $file 是否存在
    if [ ! -f "$file" ]; then
      touch "$file"
    fi
    
    # -n 判断一个变量是否有值
    if [ ! -n "$var" ]; then
      echo "$var is empty"
      exit 0
    fi
    
    # 判断两个变量是否相等
    if [ "$var1" = "$var2" ]; then
      echo '$var1 eq $var2'
    else
      echo '$var1 not eq $var2'
    fi
    

    转载请注明:爱开源 » linux bash判断文件或文件夹是否存在