Welcome to

快雪Tang

Home / shell

Bash Tricks: string

Bash 字符串操作极其强大,尽管还无法和高级语言的能力相比肩,但在bash中你已经几乎可以完全操纵任何文本、任何字符串了。   字符串操作和变量有密切关联性,所以先介绍变量及其表达式的使用惯例: ${var} 变量var的值, 与$var相同 ${var-DEFAULT} 如果var没有被声明, 那么就以$DEFAULT作为其值;否则其值为 $var ${var:-DEFAULT} 如果var没有被声明, 或者其值为空, 那么就以$DEFAULT作为其值;否则其值为 $var ${var=DEFAULT} 如果var没有被声明, 那么就以$DEFAULT作为其值;否则其值为 $var ${var:=DEFAULT} 如果var没有被声明, 或者其值为空, 那么就以$DEFAULT作为其值;否则其值为 $var ${var+OTHER} 如果var声明了, 那么其值就是$OTHER;否则就为null字符串 ${var:+OTHER} 如果var被设置了, 那么其值就是$OTHER;否则就为null字符串 ${var?ERR_MSG} 如果var没被声明, 那么就打印$ERR_MSG;否则其值为 $var ${var:?ERR_MSG} 如果var没被设置, 那么就打印$ERR_MSG;否则其值为 $var ${!varprefix*} […]

Read More

bash tricks: no alias, in source, …

BASH: \ls 前缀\的目的是避免alias替换,使用命令的原生目标来执行。当 alias ls=’ls –color’ 时,ls的输出结果是带高亮色的,\ls则避免了alias替换,输出结果没有高亮色。   BASH:函数名 function test_func() { echo “Current $FUNCNAME, \$FUNCNAME => (${FUNCNAME[@]})” another_func echo “Current $FUNCNAME, \$FUNCNAME => (${FUNCNAME[@]})” } $FUNCNAME是一个数组,包含倒序的函数名调用栈。例如“(child_func parent_func main_entry main)”,其中main_entry是首个函数调用入口,然后依次嵌套调用函数 parent_func 和 child_func,而main是一个伪函数名,它表示整个脚本文件。   BASH:避免多次source BASH自身检测SOURCE状态 使用一个环境变量来标识已经source过了 _sourced_=”__sourced_$$__” echo “Flag […]

Read More

bash tricks: 变量及其生存周期

本想讲述的清楚一点,然而发觉不够耐心,只好简单顺序地描述一下了 Bash 变量及其作用域 可以在bash脚本中定义变量。也可以在命令行交互过程中使用变量。在这些情况下,变量的定义方式都是相同的: A=1 echo $A 变量在定义之后一直有效,除非你取消它: A= unset A A= 可以为变量赋以空值。而 unset A 会完全取消该变量的存在性。 如果有必要,你可以使用 export 关键字来导出变量到环境变量中。 对于每一个shell实例来说,环境变量池是该shell实例的一个附着的空间,你可以丢入一堆变量。在一个shell中你可以执行多个shell脚本文件,对其中的每个脚本文件的执行实例来说,都有一个环境变量池的副本从当前shell实例复制而来,所以你在一个脚本文件中 export 某个变量A,那么A就被放入了该脚本文件实例的附着的环境变量池副本中。这个道理也适用于子shell的情况,因为调用执行一个脚本文件时就相当于fork了一个新的子shell实例,该新实例分享了当前shell实例的变量池的副本,因此在子shell中对变量的修改不会传递到父shell中。 那么,使用export有什么用处呢?我们知道,在当前shell环境下,执行一个脚本文件后,其中的变量会无效;source一个脚本的话,变量会继续可用。不过接着进行下一步,假设我们source了一个脚本文件使得变量A可用,然后进一步执行第二个脚本文件,这时在第二个脚本文件中A会是无效的,原因就在于第一步的变量A只是在当前shell环境中可用,但并不在当前的环境变量中,因此执行新脚本时A不会随着环境变量池一同被副本给新脚本。请注意,这时候就是export有用的时候了。 #!/bin/bash A=1 source A3.sh    # A3.sh 有 A=3 语句 echo $A  # 会显示 3 ./echoA.sh  # […]

Read More

bash rename,批量重命名就靠它了

bash中重命名文件一般是使用内置命令mv来完成的。mv的本质含义是移动一个文件,在bash中使用它则无须在文件系统中查找命令文件。 然而mv的语法受到很多限制,如果你需要重命名一批文件的话,它就不合适了。 幸运的是还有 rename 这条命令,而且在绝大多数 linux 发行版中,rename都是存在的并且表现一致。 rename 批量重命名可以使用 rename 命令,这个命令允许你使用正则式完成一堆文件名的策略性重命名操作。 rename的语法如下: Usage: rename [ -h|-m|-V ] [ -v ] [ -n ] [ -f ] [ -e|-E *perlexpr*]*|*perlexpr* [ *files* ] Options: -v, -verbose Verbose: print names of files […]

Read More

ops-toolset history 1

几年前在公司开发了一整套运维服务器脚本工具集,命名为 xxx OPS Toolset。 记得当年更迭了N多个版本之后,才最终成型,因为bash的编程能力在结构化组织上还是有限的,所以那时候也是下了功夫的。 现在公司的服务器群全部迁离了阿里云,这套工具集也顺应变化更新了若干次,最主要的变化是现在更通用了,不限于哪个公有云,几乎都能自适应。当然,新的版本乃至旧的版本目前还不能放出来;不过旧版本的截图,昨夜整理时发现,倒是可以post出来,也是对几年前工作的一个小小的回顾吧。 至于说框架结构,实际上我还是整理了两套的,分别是: bash-framework: https://github.com/hedzr/bash-framework bash.sh: https://github.com/hedzr/bash.sh bash-framwork 呢,基本上是 ops toolset 的框架结构,也可以说是一个最小集合的Bash脚本编程框架,主要面向 DevOps 管理任务。 因此,默认的函数集合中包含了像 package-install, is_package_installed, if_ubuntu, if_centos, is_root 这类辅助函数。 不过,由于安装主站的vps不稳定,所以它的分发大约是有问题的,需要的朋友自己去拉源码再自行改造适用了。 至于 bash.sh 就微型得多了。 bash.sh主要是面向单文件开发。bash-framwork主要是面向整套脚本集合的组织、开发,适合组织成系列的大型脚本集合。反过来说 bash.sh 则是一个快速的起点,例如你需要在建设rabbitmq集群方面做一套子命令集合,那就可以直接clone bash.sh的主文件改成 rmq-ctl,然后直接编写bash函数到这个文件中,就可以使用像 rmq-ctl init 3 nodes 这样的命令了。所以像 sdkman 那样的命令套装,用 bash.sh 可以很容易实现。 […]

Read More

运维账户免密sudo

因为背不住,也不想转到脚本那边去check源码,所以快速笔记一下: groupadd -g222 devops groupadd -g225 admin groupadd -g333 hzadmin cat >/etc/sudoers.d/hzadmin<<EEE %devops  ALL=(ALL) NOPASSWD:ALL %hzadmin  ALL=(ALL) NOPASSWD:ALL %admin  ALL=(root) NOPASSWD: /bin/systemctl EEE usermod -aG hzadmin,devops me sudo 命令免密的关键,在于 NOPASSWD:ALL。如果想要给特定账户而不是账户组授予特定权限,则可以用: someone ALL=(root) NOPASSWD: /bin/systemctl 这个示例可以给账户someone授予执行systemctl的权利。类似的journalctl也可以这么做。 不过,也可以选择将账户加入到某个特定组,例如adm组、或者www-data组,的方式来使其具有特别权利。      

Read More

shell redirects

strip stdout output, and redirect the stderr output to stdout: openssl s_client -showcerts -connect example.com:443 </dev/null 2>&1 1>/dev/null merge stderr to stdout, and strip all of them: openssl s_client -showcerts -connect example.com:443 </dev/null 1>/dev/null 2>&1    

Read More

Ubuntu 14.0.4/Mac 安装nodejs开发或生产环境 (rvm)

首先来讲,Mac上可以有几种安装nodejs开发环境的方法,然而各种坑我都踩过了,还是建议rvm来安装nodejs,事实上好像我现在并没有遇到什么古怪的问题了,所以这篇文章其实并不能解决初学者的所有问题,顶多只是把一种最佳流程给记录下来罢了。 首先还是上脚本,适用于Ubuntu,Bash环境,同时也适用于Mac的Terminal/iTerm2环境(但需要一点点更改,主要是去掉apt-get相关的指令):

Read More