ssh-copy-id: Bourne shell script text executable
ssh-copy-idは便利だね。何も考えたくなければこれでいいし。
$ ssh-copy-id myuser@example.com
中身はシェルスクリプトだったりする。
$ file /usr/bin/ssh-copy-id /usr/bin/ssh-copy-id: Bourne shell script text executable
cat /usr/bin/ssh-copy-id すると中身は結構短い。
#!/bin/sh # Shell script to install your id_rsa.pub on a remote machine # Takes the remote machine name as an argument. # Obviously, the remote machine must accept password authentication, # or one of the other keys in your ssh-agent, for this to work. ID_FILE="${HOME}/.ssh/id_rsa.pub" 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 should leave $1 as the target name fi else if [ x$SSH_AUTH_SOCK != x ] ; then GET_ID="$GET_ID ssh-add -L" fi fi if [ -z "`eval $GET_ID`" ] && [ -r "${ID_FILE}" ] ; then GET_ID="cat ${ID_FILE}" fi if [ -z "`eval $GET_ID`" ]; then echo "$0: ERROR: No identities found" >&2 exit 1 fi if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then echo "Usage: $0 [-i [identity_file]] [user@]machine" >&2 exit 1 fi { eval "$GET_ID" ; } | ssh $1 "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys" || exit 1 cat <<EOF Now try logging into the machine, with "ssh '$1'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. EOF
shは便利なんだけど、こういう書き方をしないとNULLSTRINGのチェックができないのは未だになれない。10年たってもなれない。
if [ x$SSH_AUTH_SOCK != x ] ; then
いつも authorized_keys のタイプ間違えそうになるので ssh-copy-idとても便利です。ssh-copy-idはたいへん便利です。
base64の備忘録
とりあえず、base64をしたかったのですが、調べると色々な方法があるなぁ、と思ったので備忘録。
opensslコマンド
一番よく使う方法かな。
$ echo -n dharry | openssl enc -base64 ZGhhcnJ5 $ echo "ZGhhcnJ5" | openssl enc -d -base64; echo dharry
base64コマンド
Linuxだとこれかな。coreutilsは便利だけど他のUNIXだとなかったりするんだな。
$ echo -n dharry | base64 ZGhhcnJ5 $ echo -n "ZGhhcnJ5" | base64 -d; echo dharry $ rpm -qf /usr/bin/base64 coreutils-5.97-34.el5_8.1
nkfコマンド
これはこれで便利
$ echo -n "dharry"| nkf -MB; echo ZGhhcnJ5 $ echo -n "ZGhhcnJ5"| nkf -mB; echo dharry
perl
perlはどのUNIXでもあるから一番楽かも。でもHP-UX11.00ぐらいだと厳しい。
$ echo -n "dharry" | perl -MMIME::Base64 -0777 -ne 'print encode_base64($_)' ZGhhcnJ5 $ echo -n "ZGhhcnJ5" | perl -MMIME::Base64 -ne 'print decode_base64($_)'; echo dharry
ruby
$ echo -n dharry | ruby -r base64 -e 'puts Base64.encode64(STDIN.read)' ZGhhcnJ5 $ echo -n ZGhhcnJ5 | ruby -r base64 -e 'puts Base64.decode64(STDIN.read)' dharry
python
$ echo -n dharry | python -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" ZGhhcnJ5 $ echo -n ZGhhcnJ5 | python -c "import base64,sys; base64.decode(sys.stdin,sys.stdout)" dharry
PowerShell
コマンドレットは便利と思ったけどいまだになじめない。慣れは重要ですね。
PS C:\Users\dharry> $str = "dharry" PS C:\Users\dharry> $str = [Convert]::ToBase64String([System.Text.Encoding]::GetEncoding("iso-2022-jp").GetBytes($str)) PS C:\Users\dharry> $str ZGhhcnJ5
tcl
tclshで試してみた。centosのtclだとbase64ライブラリがなかったのでActiveStateのActiveTCL8.5.11.1で確認。
% package require base64 2.4.2 % base64::encode "dharry" ZGhhcnJ5
curl
apacheのbasic認証に渡すときはbase64にしているのでwgetもcurlでもいけるはずだ。でも少しawkで頑張れば行けると思うけど面倒だから使わない。
$ curl -vu dharry: http://example.com 2>&1 | awk '{ if($0 ~/Authorization/) print $(NF)}' ZGhhcnJ5Og== $ echo -n ":" | base64 Og==
vbs
なんだかvbsが嫌になってきた。
Private Function base64(str) Dim dom, elem, bin, result Set st = CreateObject("ADODB.Stream") With st .Type = 2 .Charset = "Shift-JIS" .Open .WriteText str .Position = 0 .Type = 1 bin = st.Read .Close End With Set dom = CreateObject("Microsoft.XMLDOM") Set elem = dom.CreateElement("tmp") elem.DataType = "bin.base64" elem.NodeTypedValue = bin result = elem.Text base64 = result End Function Wscript.echo base64("dharry")
単語を数える例のやつ
wordcountの例題は map/reduce でよくでてくるよね。
ruby
rubyは便利。
array = %w(foo bar hoge foo foo bar fuga hoge) h = Hash.new(0) array.each {|e| h[e]+=1} p h #=> {"fuga"=>1, "foo"=>3, "hoge"=>2, "bar"=>2}
perl
perlも便利。初期化しなくてもいいのかしら。
use Data::Dumper; my @array = qw(foo bar hoge foo foo bar fuga hoge); my %h = {}; foreach my $e (@array) { $h{$e}++; } print Dumper(\%h); #=> #$VAR1 = { # 'bar' => 2, # 'fuga' => 1, # 'foo' => 3, # 'hoge' => 2, # 'HASH(0x12af940)' => undef # };
bash4
bash の version 4 からは連想配列が使える。知らない間に機能アップしている。
array=(foo bar hoge foo foo bar fuga hoge) declare -A h # 連想配列hを宣言 for e in ${array[@]}; do h[$e]=$(( h[$e] + 1 )) done # ${h[*]}はvalues, ${!h[*]}はkeys for e in ${!h[*]}; do echo "$e => ${h[$e]}" done #=> #fuga => 1 #bar => 2 #foo => 3 #hoge => 2
bash3
CentOS5/RHEL5だとbash version 3 だから連想配列は使えない。どうしようかと思ったけど意外とシンプルにかけました。連想配列が使えるawkで書けばいいというオチもありますね。
vardir=/dev/shm/var.$$ array=(foo bar hoge foo foo bar fuga hoge) [ ! -d $vardir ] && mkdir -p $vardir for e in ${array[@]}; do echo -n 1 >> $vardir/$e done cd $vardir ls -l * | awk '{ print $5, "=>", $NF}' \rm -fr $vardir #=> #bar => 2 #foo => 3 #fuga => 1 #hoge => 2
シェルスクリプトをコンパイルできるshcで遊んでみた
使うことはないかもしれない。でも面白いです。
shcをインストール
$ sudo apt-get install shc
なかったらソースをダウンロードしてコンパイルしてください。
$ wget http://www.datsi.fi.upm.es/~frosal/sources/shc-3.8.7.tgz $ tar xvzf shc-3.8.7.tgz $ cd shc-3.8.7/ $ make
shcでコンパイル
テストで /usr/bin/ldd を使用。 なんで lddってshell script ってイメージがないんだろう。
$ file /usr/bin/ldd /usr/bin/ldd: Bourne-Again shell script text executable $ cp -p /usr/bin/ldd . $ ./shc -v -r -T -f ./ldd shc shll=bash shc [-i]=-c shc [-x]=exec '%s' "$@" shc [-l]= shc opts= shc: cc ./ldd.x.c -o ./ldd.x shc: strip ./ldd.x shc: chmod go-r ./ldd.x $ file ./ldd.x ./ldd.x: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped $ ./ldd.x /bin/ls linux-vdso.so.1 => (0x00007fff0d9ff000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f2ed8878000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f2ed8670000) libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007f2ed8467000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2ed80d3000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2ed7ecf000) /lib64/ld-linux-x86-64.so.2 (0x00007f2ed8a9f000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2ed7cb0000) libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007f2ed7aab000)
foo.x.c というCのソースができるので、中身を眺めてみるのもオツなものです。
仕事がダラけてしまったのでシェルスクリプトでプログレスバーやってみた
やっぱ、プログレスバーがないと動いているのか分からなくてイラっとくるよね。というので、シェルスクリプトでプログレスバーを簡単にできないかな、と思い書いてみた。
progress() { _bar=$1; _bar=${_bar:=.} while : do jobs %1 > /dev/null 2>&1 [ $? = 0 ] || break echo -n ${_bar} sleep 0.1 done; } usage() { echo "usage:$0 [command]"; exit; } [ $# = 0 ] && usage "$@" & progress
上記コードをprogress.shとして、こんな感じで時間がかかりそうな処理のコマンドを引数に渡してあげればOK.
./progress.sh sleep 10 ..............................................................................................
barコマンド
しかし、探せばこんなごみコード書かなくても便利なものがあったりもする。このbarコマンドはcatのプログレスバー付きコマンドという感じです。これ、すげー便利じゃないですか。最初からこれにすればよかった。
http://www.theiling.de/projects/bar.html
まずはテストゴミファイル
dd if=/dev/urandom of=hoge.img bs=1M count=10
圧縮してバックアップ。
./bar -n hoge.img | gzip -1 > hoge.img.gz 91% [==============================================================......]
圧縮ファイルの展開。
./bar -n hoge.img.gz | gzip -d -c > hoge-new.img 85% [==========================================================..........]
ファイルのコピー。
でもこの -o オプションは 「 -o FILE (Redirects output to a file.)」 とアウトプットするファイルを指定するので、通常のcpとは順番が逆になる。 「cp source dest」 ではなく 「bar -o dest source」 間違えやすいのに間違えるとコピー元ファイルは0バイトになってしまう漢らしいシンタックスだ。
./bar-1.4$ ./bar -o dst src 60% [=========================================...........................]
潔し、っていうコマンドはいいですね。身が引き締まります。
Bashの変数パラメータ展開はやっぱし便利
パターン照合演算子ってやつは便利だなーとしみじみ思ったので。
バイト数だしたり
$ x="/usr/share/apt/ubuntu-archive.gpg" $ echo ${#x} 33
切り出したり (${parameter:offset:length})
$ x="/usr/share/apt/ubuntu-archive.gpg" $ echo ${x:1:3} ${x:5:5} ${x:11:3} ${x:15:18} usr share apt ubuntu-archive.gpg
置換したりできる。
x="sumomo mo momo mo momo no uchi" $ echo $x sumomo mo momo mo momo no uchi $ echo ${x//momo/} su mo mo no uchi $ echo ${x//momo/banana} subanana mo banana mo banana no uchi
basenameやdirnameコマンドぽいこともできる。
_basename() { local path=$1 echo ${path##*/}; } _dirname() { local path=$1 echo ${path%/*}; } _basename2() { local path=$1 echo `_basename ${path%.*}`; } _extname() { local path=$1 echo ${path##*.}; } usage() { >&2 echo usage: $0 [path] exit 1; } [ $# -ne 1 ] && usage for func in _basename _dirname _basename2 _extname do echo "${func}(): `eval $func $1`" done
結果はこんなかんじ。
$ ./test.sh /usr/share/apt/ubuntu-archive.gpg _basename(): ubuntu-archive.gpg _dirname(): /usr/share/apt _basename2(): ubuntu-archive _extname(): gpg
シェルの乱数の覚書
いろいろあるんだな、って思った。
$ echo $$ 25653 $ awk 'BEGIN { print PROCINFO["pid"] }' 26712 $ echo `date +%s` 1290451043 $ echo $RANDOM 28006 $ awk 'BEGIN{ srand(); print rand() }' 0.384664 $ awk 'BEGIN { srand(systime() + PROCINFO["pid"]); print rand() }' 0.270381 $ od -vAn -N4 -tu4 < /dev/urandom 177439376 $ od -An -N2 -i /dev/random 25895 $ dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -f1 -d" " 655519971
参考
- http://www.linuxquestions.org/questions/programming-9/shell-script-random-variable-4088/
- http://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/randomvar.html
- http://journal.mycom.co.jp/articles/2010/04/30/shell-random-number/index.html
- http://awk.info/?doc/tip/random.html
- http://d.hatena.ne.jp/hycon/20101007/1286450035