FPs

Articles with the shell tag

echo 输出导致SCP 失效的问题

搭建了一个跳板机,强制使用密钥对登陆机器,同时需要用户在本地开启ForwardAgent,跳板机上创建SSH_AUTH_SOCK,透传私钥。然而常常有用户在本地没有正确配置,导致上了跳板机之后,再SSH 就会失败,于是我在跳板机的.bashrc 上写了一段检测脚本,如果变量$SSH_AUTH_SOCK 不存在,就引导用户去看Wiki,不要烦我啦!

用了一段时间,有用户发现scp 文件到跳板机时会失败,Google 一下:SCP doesn't work when echo in .bashrc?,怎么判断当前会话是scp?:Can I tell if I'm in an scp session in my .bashrc?

改下脚本:

if [ -n "$PS1" ] && [ -z $SSH_AUTH_SOCK ];then
   echo ""
   echo "创建SSH_AUTH_SOCK 失败!"
   echo "1.请在本机执行 ssh-add 添加私钥至 ssh-agent"
   echo "2.请在~/.ssh/config 配置:ForwardAgent yes"
   echo "详细帮助:wiki..."
   echo ""
fi

搞定!


一个改良的Ping

Ping 是一个非常常用的命令,有2种情况会使用它:
一是会从浏览器的地址栏或者其他人发给我的网址,复制,然后进行ping,带着协议以及一堆uri和args,
例如: https://accounts.google.com/AddSession?hl=en...
二从Linux 系统的网络地址复制过来IP,进行Ping,带着掩码位数,
例如:192.168.1.1/32

以上2种情况,如果直接复制内容到终端,然后ping,会提示:

ping: cannot resolve ....: Unknown host

很恼人,写一个简单的脚本:

#!/usr/bin/env bash
#author: fangpeishi@gmail.com
#issues:
#  - http(s)://xxx.xx/xxx/xx?xxx
#  - 192.168.1.1/32

new_args=`echo $@ |sed  's/http.*\:\/\///' |sed 's/\/[^ ]*//'`
#echo ${new_args}
ping ${new_args}

把这个脚本命名为pin, 放到 /bin 之类的目录下面即可(本来想做成alias,没成功),最终效果如下:
pin


记一个退出终端进程不退出的问题

某一天开发同学问了一个问题,他们在线上跑一个job,没用screen,nohup,把iTerm 窗口关了,job 没挂。再登录进去看,PPID 变成1,即进程被init 进程接管。
在对应机器上执行shopt, 发现:

...
gnu_errfmt      off
histappend      off
histreedit      off
histverify      off
hostcomplete    on
huponexit       off
interactive_comments    on
lastpipe        off
lithist         off
login_shell     on
mailwarn        off
...

注意CentOS 7 默认将huponexit 设为off 了,这样在用户将Shell 退出结束会话时,系统不会发送 SIGHUP 给所有进程,这效果其实类似使用了nohup,nohup 的作用就是忽略HUP 信号。

huponexit
  If set, bash will send SIGHUP to all jobs when an interactive login shell exits.

Google Shell 编程风格指南

背景

使用哪种Shell

Bash 是唯一被允许用于编写可执行文件的Shell 脚本语言(译注:存在多种Shell语言,可参考Wikipedia:Unix_Shell
可执行文件必须以#!/bin/bash 开始(译注:Wikipedia:Shebang),并且使用最小数量的执行选项(译注:Find out what your UNIX shell’s flags are & then change them, The Set Builtin)。
使用set设置shell 执行选项,以便用bash <脚本名> 的方式调用脚本时候不会破坏执行选项的功能。
限制所有的可执行shell 脚本统一使用bash 使得我们在机器上能统一安装一种shell 。 唯一的例外,你正在编写的项目强制你使用其他shell 语言。例如Solaris SVR4 软件包要求包内的任何脚本用纯Bourne shell 编写(译注:即sh,参考Wikipedia:Bourne_shell)。

什么时候使用Shell

Shell 应该只用于编写小工具或者简单的包装脚本(译注:wrapper scripts,Shell Wrappers)。
尽管shell 脚本不是一种开发语言,但在Google 内部它被用于编写各种各样的工具性脚本。在广泛的开发部署中,遵循这份编程风格指南是一种共识,而不是一个建议。

一些准则:

  • 如果你主要是调用其他工具和做相对少量的数据处理,使用shell 来完成任务是合适的选择。
  • 如果你在意性能,请使用其他工具来代替shell。
  • 任何情况下,如果你发现需要使用数组(译注:Bash:Array variables),并且不是使用${PIPESTATUS}(译注:PIPESTATUS 保存着管道中各命令的返回值),你应该使用Python。
  • 如果你要编写一份超过一百行的Shell 脚本,你应该尽量使用Python 来编写。记住,随着Shell脚本行数的增长,尽早使用其他语言来重写你的脚本,以免将来重写的时候浪费更多的时间。
Continue ->

一键连接VPN

公司安全的同事最近给OpenVPN加上了基于Google Authenticator的二步验证,密码是「常用密码」+「每次变化的Token」,每次在外边想做事都得打开手机查看Token,输入密码串,安全是安全了,可是不能忍!

OSX 生成Token

首先想到的是不要每次都打开手机,所以开始寻找Google Authenticator 生成工具的桌面版,果然有很多解决方案Is there a Google Authenticator desktop client?, 有Web版的、Java版的,不过最高效的当然是命令行版oathtool:

安装oath-toolkit:

brew install oath-toolkit

一个shell脚本,拷贝到 /usr/local/bin/,加上可执行权限:

#!/bin/bash
#fork from http://superuser.com/questions/462478/is-there-a-google-authenticator-desktop-client , by Peter Beckman

scriptname=`basename $0`
if [ -z $1 ]
then
echo "$scriptname: Service Name Req'd"
echo ""
echo "Usage:"
echo "   otp google"
echo ""
echo "Configuration: $HOME/.otpkeys"
echo "Format: name=key"
exit
fi
otpkey=` grep ^$1 $HOME/.otpkeys | cut -d"=" -f 2 | sed "s/ //g" `
if [ -z $otpkey ]
then
echo "$scriptname: Bad Service Name"
exit
fi
token=`/usr/local/bin/oathtool --totp -b $otpkey`
echo $token
echo $token | /usr/bin/pbcopy #自动拷贝至剪贴板
Continue ->