Skip to main content

Posts for year 2016

bash

bashスクリプト等でよく使う機能の利用パターンを記載。

trap

When the script exits, remove tmpfile

tmpfile=/tmp/tmpfile.$$
trap "rm ${tmpfile}" EXIT

basename, dirname

use script file name and directory in the script

echo $(basename $0 .sh)
echo $(dirname $0)

pushd, popd

pushd、popdは標準出力にメッセージを吐く。スクリプトで使用する際は不要なので捨てる。

pushd . > /dev/null
cd dir
:
popd    > /dev/null

read

標準入力からの入力を変数dummyへ入れる。 (-pでプロンプトを指定。-sを指定するとエコーバックしない)

read -p "input? " [-s] dummy

比較演算

条件を満たせばtrue

演算子 説明
-z 文字列の長さ0
-n 文字列の長さ1以上
-s ファイルサイズが1以上

if

文字列の比較

if [ $str = "hoge" ]; then
:
else
:
fi

case

case "$?" in
  0)
    echo ok
    ;;
  1)
    echo ng
    ;;
  *)
    echo error
    ;;
esac

for loop

for file in /etc/ssh/ssh_host*key* ; do
:
done

while loop

条件がtrueの時だけ実行する。

while true; do
:
sleep 300
done

全ての引数に対して処理を実行する。

while [ $1 ]; do
echo $1
shift
done

while とread

while read line; do
echo $line
done < filename

または

cat filename | while read line; do
echo $line
done

printf

printf 'INSERT INTO mytable (temprature, humidity) VALUES (%f, %f);' 20.0 50.0 | sqlite3 database.db

組み込みコマンドgetoptsの使い方の例

#! /bin/bash

while getopts "hw:" opt; do
  case ${opt} in
    h)
      echo usaage
      exit
      ;;
    w)
      dow=${OPTARG}
      ;;
  esac
done
shift $((OPTIND - 1))

while [ $1 ]; do
  :
  shift
done

indirection reference

using shell

key=slackpkg
pkg_slackpkg=skackware
myos=pkg_${key}
echo ${!myos}

using eval

pkg_slackpkg=slackware
key=slackpkg
eval myos=\"\${pkg_${key}}\"
echo ${myos}

when variable is array

pkg_apt=(debian ubuntu raspbian)
pkg_yum=(rhel fedora centos)

for key in apt yum; do
  echo ${key}
  for i in `seq 0 2`; do
    eval myos=\"\${pkg_${key}[i]}\"
    echo ${i}: ${myos}
  done
done

その他

スクリプトの改行文字をCR+LFで書くと、CRが(shebang等の)コマンド(の一部)として認識され、実行エラーとなる。 スクリプトの改行文字はLFで書く。

$ bash myscript.sh
: command not found
$ chmod +x myscript.sh
$ ./myscript.sh
-bash: ./myscript.sh: /bin/bash^M: bad interpreter: そのようなファイルやディレクトリはありません

When shebang is omitted though it has executable permission (+x), when it called without shell command it may show below error message

exec user process caused "exec format error"

rename the file using a part of original file name.

$ ls | tail -4 | awk -F_ '{print "mv",$0, "foo_"$4}'

basic commands usage

よく使う基本的コマンドの使用パターンを記載。

sort

IPv4アドレスのソート例

... | sort -t. -k1n -k2n -k3n -k4n

一部一致した行の行数をそれぞれ数える

awk '{print $2 $3}' filename | uniq -c

uniq

ソートして重複行を除外

... | sort | uniq

seq

通番の範囲で繰り返して実行

for num in `seq 0 7`; do
ping -c 1 192.168.0.1${num}
done

grep

ログ確認

grep -i -E "crit|emer|alert|err|warn" /var/log/messages
dmesg | grep -i -E "crit|emer|alert|err|warn"

コメント行と空行を除く

grep -E -v "^#|^$" file

出力を抑止(リターンコード: マッチしたら0、しなかったら1、エラーは2)

grep -q pattern file

出力の前にファイル名を表示しない

grep -h pattern file1 file2 ....

cat

制御文字(タブ文字、改行文字を含む)を含めて、表示する

cat -vte filename

行番号を表示

cat -n filename

script

作業ログの取得

script [-a] [-c command] filename

nohup

ジョブをバックグラウンドで動かし、ログアウトしても続行させる。(nohupさせないと、ログアウトしたらジョブが終了する。) cshの埋め込みコマンドにも同名のものがある。

nohup command arg1 arg2 ... > logfile 2>&1 &

tail

GNUのtailは複数のファイルを与えることができる

tail -n 5 file1 file2 ...

追加されたデータを表示する

... | tail -f

mkisofs

isoイメージファイル作成

mkisofs -r -J -o filename.iso dirname

col

manの出力からバックスペースを削除してテキストに出力

man man | col -b > outfile

script

scriptでログを取得し、エスケープシーケンスを適切に処理して閲覧する。

script [-c command] [-a] [logfile]
less -R logfile

date

3週間前の日付を表示

date --date "3 weeks ago" "+%Y%m%d"

昨日の日付を表示

date --date yesterday "+%Y%m%d"

or

TEMP_TZ=$TZ
export TZ=JST+15
yesterday=`date +%Y%m%d`
export TZ=$TEMP_TZ

dump and restore

dumpとrestoreは、ファイルシステムレベルでバックアップ、リストアを行います。対応してるのはext2等に限られます。

他のOS、他のファイルシステムでも、同様のアプリケーションがあります。(FreeBSDの例)

以下、使い方の例。

レベル0バックアップ(フルバックアップ) ここではdumpdatesファイルを、デフォルトの/etc配下ではなく、/dirに保存している。

dump -0u -D /dir/dumpdates -f filename.dump /dev/sdx

レベル0からの増分バックアップする際のダンプレベルの例

0 1 1 1 1 . . .

前回からの差分バックアップする際のダンプレベルの例

0 1 2 3 4 . . .

ハノイの塔アルゴリズムの例

0 3 2 5 4 7 6 9 8  1 3 2 5 4 7 6 9 8  1 3 2 . . .
レベル0のフルバックアップは長期保存。
レベル1を週次で取得し、以後のレベルを日次で実施するといった運用。

一括リストア。 フルリストアの後、適したダンプレベルのリストアを順に行う。

cd /mnt
restore -rf filename.dump
:
rm restoresymtable
ハノイの塔アルゴリズムで増分バックした場合:
レベル8までリストアする例: 0 (1) 2 4 6 8
レベル9までリストアする例: 0 (1) 2 4 6 9

特定ファイルのみリストア

restore -xf filename.dump ./file

対話モードで選択してリストア

cd /mnt
restore -if filename.dump
> cd dir
> ls
> add file
> extract

gzipで圧縮し、ssh転送してリモートホストにバックアップ

dump -0uf - /mountpoint | gzip -c | ssh user@remotehost dd of=/dir/filename.gz
ssh user@remotehost dd if=/dir/filename.gz | gzip -cd | restore -rf -

gzipで圧縮し、ssh転送してリモートホストでリストア

dump -0uf - /mountpoint | gzip -c | ssh user@remotehost 'gzip -cd | restore -rf -'
または
ssh user@remotehost 'dump -0uf - /mountpoint | gzip -c' | gzip -cd | restore -rf -

rsync

rsync は同期ツールで、バックアップをとるのにとても重宝します。

以下、使い方のメモ。

/src配下のdirディレクトリを、/dst配下のdirディレクトリとしてコピー。 (/src/dirの内容を、/dst/dirの中にコピー。)

rsync -av /src/dir /dst
or
rsync -av /src/dir/ /dst/dir

コピー元で削除されたファイルを、コピー先で削除する。

rsync -av --delete /src/dir /dst

sshを介して、remotehostの内容をローカルにコピーする。

rsync -av -e ssh user@remotehost:/dst /src/dir 
(この場合、リモート側にもrsyncをインストールする必要がある。)

その他オプション

-n          # テスト実行
--bwlimit=n # 帯域制限(kbps)

参考: scp の帯域制限は -l n(kbps)

dd

dd はディスクイメージを保存・リストアするのに便利なコマンドです。

ifを指定しなければ標準入力を使用。同様に、ofを指定しなければ標準出力を使用します。

以下、使い方をメモしておきます。 (コピー&ペーストで利用する場合は充分気をつけて利用してください)

ディスクイメージをfilename{へ保存, リストア}する例。 (リストアのコマンドは、ベンダ等から配布されているisoイメージ等をusbメディア等 に書き込む際等によく使用されます)

dd if=/dev/sdx of=filename bs=1M
dd if=filename of=/dev/sdx bs=1M

gzipで圧縮して{保存, リストア}する例。

dd if=/dev/sdx bs=1M | gzip -c filename.gz
gzip -cd filename.gz | dd of=/dev/sdx bs=1M

ディスクイメージを、gzipで圧縮・転送し、remotehostのfilename.gz{へ保存, からリ ストア}する例。

dd if=/dev/sdx bs=1M | gzip -c | ssh user@remotehost dd of=filename.gz
ssh username@remotehost dd if=filename.gz | gzip -cd | dd of=/dev/sdx bs=1M

ディスクイメージを、gzipで圧縮・転送し、remotehostのディスク{へ, から}直接リス トアする。

dd if=/dev/sdx bs=1M | gzip -c | ssh user@remotehost 'gzip -cd | dd of=/dev/sdx bs=1M'
または
ssh user@remotehost 'dd if=/dev/sdx bs=1M | gzip -c' | gzip -cd | dd of=/dev/sdx bs=1M

create empty file

dd if=/dev/zero of=file.img bs=1M count=512
mkfs -t ext4 file.img
mount -o loop file.img /mnt

sparse file

dd if=/dev/zero of=file.img bs=1M count=0 seek=512
ls -lhs file.img
tar cSf tarfile.tar file.img

These image files could be used as block devices by loopback device. At first find available loop device. Then use it.

$ losetup -f
$ losetup /dev/loop0 file.img
$ losetup -a

$ mkfs -t ext2 /dev/loop0 100
$ mount -t ext2 /dev/loop0 /mnt
$ umount /dev/loop0
$ losetup -d /dev/loop0

When you mount an image backup file which has partition table, it need to specify offset:

$ fdisk -l file.img
$ mount -o loop,ro,offset=$((sector_size*start_position)) file.img /mountpoint

or

$ kpartx -a -v file.img 
$ mount /dev/mapper/loop0p1 /mountpoint
$ umount /mountpoint
$ kpartx -d -v file.img

wipe a disk

$ dd if=/dev/zero of=/dev/sdx bs=4096
$ dd if=/dev/urandom of=/dev/sdx bs=4096

or you can use shred command.

$ shred --verbose --random-source=/dev/urandom -n 1 /dev/sdx

docker life cycle

ライフサイクルをざっと。

dockerデーモンの起動と動作確認。ubuntuの場合。

$ sudo service docker status
$ sudo service docker start
$ sudo docker run --rm hello-world

リポジトリに登録されているイメージを取得する。

$ sudo docker pull debian:latest
Pulling repository debian
6845b83c79fb: Download complete
575489a51992: Download complete
Status: Downloaded newer image for debian:latest
$ 
$ sudo docker images debian
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
debian              latest              6845b83c79fb        13 days ago         125.1 MB
$

コンテナを作成して実行。コンソール接続してbashを実行する例。

$ sudo docker run -it debian:latest /bin/bash
root@06e1a850e923:/# 
root@06e1a850e923:/# w
 22:20:47 up 29 days, 14:32,  0 users,  load average: 0.36, 0.29, 0.24
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root@06e1a850e923:/#
root@06e1a850e923:/# uname -a
Linux 06e1a850e923 3.13.0-63-generic #103-Ubuntu SMP Fri Aug 14 21:42:59 UTC 2015 x86_64 GNU/Linux
root@06e1a850e923:/#
root@06e1a850e923:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
NAME="Debian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=debian
HOME_URL="http://www.debian.org/"
SUPPORT_URL="http://www.debian.org/support/"
BUG_REPORT_URL="https://bugs.debian.org/"
root@06e1a850e923:/#

コンソール接続したコンテナから一旦切断する例。

root@xxxxxxxxxxxx:/# [Ctl+p]-[Ctl+q]
$ 
$ sudo docker ps | grep debian
xxxxxxxxxxxx        debian:latest       "/bin/bash"         About a minute ago   Up About a minute                       berserk_mayer
$

再接続する例。

$ sudo docker attach xxxxxxxxxxxx
root@xxxxxxxxxxxx:/#

コンテナを終了する例。

root@06e1a850e923:/# exit
exit
$

終了したコンテナを再起動する例。

$ sudo docker ps -a | grep debian
xxxxxxxxxxxx        debian:latest            "/bin/bash"            13 minutes ago      Exited (0) 13 seconds ago                                          berserk_mayer
$
$ sudo docker start -i xxxxxxxxxxxx
root@xxxxxxxxxxxx:/# 
root@xxxxxxxxxxxx:/# exit
exit
$

コンテナの状態確認。

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$ 
$ sudo docker ps -a | grep debian
06e1a850e923        debian:latest            "/bin/bash"            2 minutes ago       Exited (0) 47 seconds ago                                      evil_kowalevski

$

copy file from/to docker container

$ sudo docker cp xxxxxxxxxxxx:/dirname/filename destination
$ sudo docker cp source xxxxxxxxxxxx:/dirname/filename

コンテナの削除。

$ sudo docker rm 06e1a850e923
06e1a850e923
$ 
$ sudo docker ps -a | grep debian
$

イメージの削除。

$ sudo docker rmi debian:latest
Untagged: debian:latest
Deleted: 6845b83c79fb642ed6af06cceaca042e155717ca8eb0b5cffa9c43f1f7f70348
Deleted: 575489a51992d5d30976ff5ba7f7eabdc134acfb51c79ff48883089009594e64
$
$ sudo docker images debian
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
$

dockerイメージの作成

$ mkdir project && cd project
$ 
$ vi Dockerfile
$ 
$ sudo docker build -t imagename:tagname . | tee build.log
$ 
$ sudo docker images imagename
$

When you want to use proxy, use --build-arg option like bellow

$ sudo docker build --build-arg http_proxy=http://192.168.xxx.xxx:3142/ -t imagename:tagname . | tee build.log

When new image name is , then rename it as below

$ sudo docker tag xxxxxxxxxxxx imagename:tagname
$ 
$ sudo docker images imagename

不要なイメージの一括削除

sudo docker images | awk '$1~/<none>/ {print}'
sudo docker images | awk '$1~/<none>/ {print $3}' | xargs sudo docker rmi

使用するdockerfileの簡単な例。

From debian:latest
RUN apt-get update && apt-get install -y \
    screen \
    openssl \
    vim \
   make \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

Tiny Tiny RSS

Tiny Tiny RSSは、フリーのサーバサイドRSSアグリゲータです。

利用するには、構築済みの方にアカウントを払い出してもらうか、自分でwebサーバ、dbサーバを構築・運用していく必要があります。

スマホのニュースアプリと比較して、RSSアグリゲータは、ニュースソースをお仕着せのものではなく自分で選択することができること、アプリ等が突然サービス終了して泣かされることがないことが利点です。

RSSアグリゲータといえば、数年前にgoogleのサービスが終了し、今度はYahoo!Japanのサービスが終了することになりました。 自前でサーバを動かしていれば、サービスの終了に怯える必要がありません。

データがサーバにある利点は、複数の端末から同じデータにアクセスすることができること、クライアント端末に問題があってもデータは安全なことです。 サーバ上のデータの安全性は、サーバの冗長度によります。

自分の場合は安価なVPSを借りて自前で構築・運用しています。もう随分前なのであやふやですが、構築自体は難しくなかったと記憶してます。再構築することがあれば、手順を記載したいと思います。

コンテンツはWebブラウザでアクセスすることもできるし、専用のクライアントソフトから見ることもできます。

スマホで動く専用のクライアントもいくつかあります。自分が使っているのは、以下の2つです。

iPhone版のほうが自分には使いやすい気がします(Androidが好きな自分としては非常に悔しいけど)。

If you get an error 'Your access level is insufficient to run this script' after you update tt-rss, temporary update your account settings.

$ sudo docker exec -it work_postgres_1 psql -U ttrss
# SELECT access_level FROM ttrss_users WHERE login = 'yourname';
# BEGIN;
# UPDATE ttrss_users SET access_level = 10 where login = 'yourname';
# SELECT access_level FROM ttrss_users WHERE login = 'yourname';
# COMMIT;

After update, set it back as before

# BEGIN;
# UPDATE ttrss_users SET access_level = 0 where login = 'yourname';
# SELECT access_level FROM ttrss_users WHERE login = 'yourname';
# COMMIT;
# \q

arukas

2019/10追記

2020/1/31でのサービス終了が発表されました。すでに新規アカウントの申し込みは終了しています。 無料で使える範囲での活用方法を自分の中で見いだしたところでしたので、とても残念です。 大手サービスプロバイダなのに、2018/03 から始まったサービスが 2020/01 で終了してしまうというのは、あまりに早すぎると感じます。利用者が相当少なかったのでしょうか。

2018/04追記

2018/03下旬からサービスインとなっています。βテストの時との違いや気づいた点を記載します。

  • 利用するには、アカウント作成(招待制)とクレジット情報の登録が必要です。 (無料のプランしか使う予定が無くてもクレジット情報が必要なようです。)
  • 転送量は無料。当初の予告どおり、無料で使えるFreeプランもあります。 (Freeプランでは0.1vcpu、メインメモリ128MB、同時に作成しておけるコンテナは一つだけ、実行できるのも一つだけ。)
  • ドメイン名にtokyoと入っていますが、自分が試したときはIPアドレスは大阪方面のものと判定されました。 (βを使い始めた頃は東京方面のアドレスと判定されましたが、以後どうなったのか確認してません)
  • コントロールパネルのコンテナ作成画面は、利用するプランの選択肢がある以外は、βの時と同じに見えます。

自分にとって「東京(のアドレス)で(無料で)使えるサーバ」というのが、非常に価値が大きかったので、ちょっと残念な感じもあります。 いずれにせよ無料で使えるプランがあるのはありがたいですので、 いろいろ制限がある中、どんなことがどこまでできるのか、試してみたいと思ってます。

2017/08追記

2017/07末をもってβテストが終わりました。そのまま正式サービスに移行するのではなく、一旦サービスを止めたようです。 正式サービスの開始時期は今のところ未定とのことです。

追記ここまで。

arukasは、コンテナ技術のdockerを利用したホスティングサービスです。

逆から読むと、sakura。さくらのVPSでおなじみの、さくらインターネットのサービスです。 無料で利用することができるオープンβテストが4月末ごろから9月末までの予定で行われており、間もなく正式リリースとなるものと思われます。 正式リリースした後も無料で利用できるプランが設定されるようです。

arukasでは、Docker Hubパブリックレポジトリにアップロードされたコンテナを登録して、起動することができます。 Docker Hubには沢山のレポジトリが登録されていますが、自分で作成・登録することもできます。 無いものは自分で作ってしまえばいいので、実際には、どんなコンテナでも動かすことができます。

dockerの利点は、コンテナの作成・起動・終了・削除が迅速にできることで、これはそのままarukasにも当てはまります。 ベータテストのためなのか、以下の制限があります。

  • データ永続化の仕組みがないので、再起動するとデータが消える。
  • 定期的(週に一度くらい?)に再起動される。

そのため永続的に使いたいデータは、外部に置く必要があります。 正式リリース後には変更される可能性もあるかもしれません。

URLとポートを指定すれば、起動したコンテナに外部から接続することができます。この場合は通信プロトコルはhttp(s)に限りません。

同じ内容のものを複数のコンテナで動かすことができますが、この場合、エンドポイントという与えられたurlにhttps接続することで、各コンテナにロードバランスして接続させることができます。(バランスさせるアルゴリズムなどは公開されていないようです。) この時、tlsにより通信内容は暗号化されます。自分で証明書を準備する必要がありません。ただし、プロトコルはhttpに限られます。

chronicle

chronicle

Markdown等のテキストファイルを、ブログ形式でhtmlファイルに変換するソフトです。 できたファイルを全てWebサーバに配置するだけで、(全世界に向けて)公開することができるようになります。

このサイトがまさにこれを利用しています。 (2020/07: I used chronicle to compile this web site for a long time. I found it has been superseded by a replacement application written in golang, called ephemeris. Taking this opportunity, I replaced it to nikola )

ブログといえばコンテンツをデータベースに保存しておいて、アクセスがあるたびに動的にhtmlファイルを生成する形のものが一般的です。 そのような場合は、webサーバ上でプログラムを実行する設定が必要となり、データベースにアクセスする権限が必要となります。

一方、chronicleのようなソフトの場合は、変換したhtmlファイルをサーバに置くだけでいいので、以下の利点があります。

  • 必要なのは公開するディレクトリへのアクセス権限だけ
  • アクセスがあるごとにファイルを生成する必要がないので、Webサーバにかかる負荷も少なくて済む

同様のソフトがたくさんある中で、chronicleを選んだ理由は、以下があげられます。

  • debian等でパッケージに入っている
  • Markdownで記載することができて、記載ルールが簡単
  • テンプレートが非常にシンプル
  • perlで動くので、追加で必要となるものが(少)ない

chronicleでも、他のソフトでできるのと同様に、使用するテンプレートを変えるだけで見た目を切り替えることができます。インストール時に数種類同梱されていますが、このサイトでは自分で作成したものを利用しています。 テンプレートは簡単なテキストファイルですので、htmlやcssの知識があれば容易に変更することができます。

サイトの見た目はテンプレートで決まるため、使うテンプレートを決めてしまえば、サイトを運用していく際にはコンテンツの内容のみを考えればいいという利点もあります。

remote access tool on android

Androidで動作するリモート接続ツールのご紹介。

ConnectBot

フリーのターミナルエミュレータです。

  • telnet、ssh。
  • ポート転送に対応。
  • 鍵認証に対応(ed25519対応)。

7インチ以上のタブレットを使用して横画面にして使えば、ソフトウェアキーボードを使うストレスはあるにしても、実用に耐えるのではないかと思います。

AndFtp

フリーのftpクライアントです。

  • ftpだけでなくsftp、scpでの接続も可能。
  • 鍵認証にも対応。

リモートとローカルファイルシステムの画面を簡単に切り替えながら作業することができます。 ワイルドカード表記を利用して表示するファイルを絞りこむ機能があり、同一ディレクトリに沢山のファイルがある場合にはすごく便利です。

ESファイルエクスプローラ

フリーのファイル管理ツール(エクスプローラ)です。

ローカルファイルだけでなく、(s)ftp、samba、webdav等、ネットワークファイルシステムにもアクセスできます。 自分は使ってませんが、Dropbox等のクラウドサービスに接続する機能もあります。

[リモートデスクトップツール]

タブレットには、rdpやvncのクライアントも入れてますが、ほとんど使うことがありません。使うようなことがあれば、書き足したいと思います。