Quantcast
Channel: Linux –俺的備忘録 〜なんかいろいろ〜
Viewing all 743 articles
Browse latest View live

dateコマンドで覚えておきたい使い方5個

$
0
0

Linux・UNIXで日時を取得する際に良く使用されるdateコマンド。
今回は、このdateコマンドで覚えておくと便利な使い方についてをまとめてみる事にする。

1.基本的な使い方

説明不要と思われるが、基本的には以下のようにコマンドを実行することで、現在のシステム時間を取得する事が出来る。

date

20150929_000001

[root@test-centos7 ~]# date
2015年  9月 29日 火曜日 05:59:42 JST

 

2.出力フォーマットを指定する

dateコマンドでは、「+」以降に以下のようなフォーマットを組み合わせて指定することで、出力される時刻のフォーマットを指定することが出来る。

%Y 西暦4桁(1970~)
%y 西暦2桁
%C 世紀
%m 月(01~12)
%b ロケール表示での月の省略名 (例: Jan)
%B  ロケール表示での月の完全名 (例: January)
%d
%e スペースで字幅調整された月の中の何日目かを表す値。%_d と同様
%H 時刻(24H)
%k スペース詰めの時 ( 0..23)。 %_H と同様
%I 時刻(AM/PM)
%l スペース詰めの時 ( 1..12)。 %_I と同様
%p AM/PM表記(大文字)
%P AM/PM表記(小文字)
%m
%s
%N ナノ秒
%a ロケール表示による曜日の省略名 (例: Sun、日)
%A ロケール表示での曜日の完全名 (例: Sunday、日曜日)
%z +hhmm 形式でのタイムゾーン (例: -0400)
%:z +hh:mm 形式でのタイムゾーン (例: -04:00)
%::z +hh:mm:ss 形式でのタイムゾーン (例: -04:00:00)
%:::z 必要な精度に応じて : が使用されるタイムゾーン表示 (例: -04, +05:30)
%Z 英字でのタイムゾーン省略形 (例: EDT)
%j 年の開始日からの日数 (001..366)
%s 1970-01-01 00:00:00 UTC からの秒数
%u 週の何日目かを表す値 (1..7); 1 が月曜日
%w 週の何日目かを表す値 (0..6); 0 を日曜日とする
%W 月曜日を週初めとした週番号 (00..53)
%U 日曜日を週初めとした週番号 (00..53)
%V ISO 週番号。月曜日を週初めとする (01..53)
%g ISO 週番号の最後の2桁 (%G 参照)
%G ISO 週番号の年部分 (%V 参照)。通常は %V と同時に使用される
%n 改行
%t 水平タブ
[root@test-centos7 ~]# # 例)YYYYMMDD_HHMMSSを表示させる
[root@test-centos7 ~]# date +%Y%m%d_%H%M%S
20150930_112417

上記フォーマットのように一つ一つを設定する他、最初からある程度まとまったフォーマットを指定する事も出来る。

%c ロケール表示での日付と時刻 (例: Thu Mar  3 23:05:25 2005)
%D 日付。 %m/%d/%y と同様
%F 完全形式の日付。 %Y-%m-%d と同様
%x ロケール表示での日付 (例: 12/31/99)
%r ロケール12時間表示での時刻 (例 11:11:04 PM)
%R 24時間表示での時および分。%H:%M と同様
%T 時刻。%H:%M:%S と同様
%X ロケール表示での時刻 (例: 23:13:48)
%j 年の開始日からの日数 (001..366)
%s 1970-01-01 00:00:00 UTC からの秒数

 

このフォーマット指定を利用して当日作業用ディレクトリの作成や一時ファイル名に使用する等、色々な使い方がある。

3.○時間後、○日前といった日時を取得する

GNU拡張されたdateコマンドの場合、「-d」オプションを使用することで○時間前後、○日前後といった指定する時刻を取得する事が出来る。
かなり柔軟な指定の仕方が出来るので、ここではその一部の例だけを紹介する。

●一日前、後の日付を求める

[root@test-centos7 ~]# # 現在の日時
[root@test-centos7 ~]# date
2015年  9月 30日 水曜日 11:50:48 JST
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 一日前の日時
[root@test-centos7 ~]# date -d '-1day'
2015年  9月 29日 火曜日 11:50:55 JST
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 一日後の日時
[root@test-centos7 ~]# date -d '1day'
2015年 10月  1日 木曜日 11:51:06 JST

●一時間前、一ヶ月後、2年後の日時を求める

[root@test-centos7 ~]# # 現在の日時
[root@test-centos7 ~]# date
2015年  9月 30日 水曜日 11:55:26 JST
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 一時間前の日時
[root@test-centos7 ~]# date -d '-1hour'
2015年  9月 30日 水曜日 10:55:38 JST
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 一ヶ月後の日時
[root@test-centos7 ~]# date -d '1month'
2015年 10月 30日 金曜日 11:55:53 JST
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 2年後の日時
[root@test-centos7 ~]# date -d '1year'
2016年  9月 30日 金曜日 11:57:24 JST

●来月の月初、3ヶ月先の月末日付を求める

[root@test-centos7 ~]# # 現在の日時
[root@test-centos7 ~]# date +%Y/%m/01
2015/09/01
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 来月の月初
[root@test-centos7 ~]# date +%Y/%m/01 -d '+1 month'
2015/10/01
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 3ヶ月後の月末
[root@test-centos7 ~]# date +%Y/%m/%d -d "-1day `date +%Y%m01 -d '+4 month'`"
2015/12/31

4.ファイルの編集日時を取得する

こちらもGNU拡張されたコマンドである必要があるが、「-r」オプションを使用することでファイルの最終更新日を取得することが出来る。

[root@test-centos7 ~]# ls -la /work/test*
-rw-r--r--. 1 root root   36814848  6月 20 19:37 /work/test.image
-rw-r--r--. 1 root root   36814848  7月 26 11:28 /work/test.image.bk
-rw-r--r--. 1 root root        237  9月  6 15:44 /work/test.log
-rw-r--r--. 1 root root        108  7月  7 20:09 /work/test.txt
-rw-r--r--. 1 root root        108  7月 26 11:28 /work/test.txt.bk
-rw-r--r--. 1 root root 1024000000  7月 11 05:12 /work/test1
-rw-r--r--. 1 root root 1024000000  7月 26 11:29 /work/test1.bk
-rw-r--r--. 1 root root         33  9月 11 07:00 /work/test123
-rw-r--r--. 1 root root 1024000000  7月 11 05:13 /work/test2
-rw-r--r--. 1 root root 1024000000  7月 26 11:29 /work/test2.bk
-rw-r--r--. 1 root root        297  9月  6 16:07 /work/test2.log
-rw-r--r--. 1 root root        230  6月  4 07:17 /work/test2.txt
-rw-r--r--. 1 root root        230  7月 26 11:28 /work/test2.txt.bk
-rw-r--r--. 1 root root        298  9月  6 16:21 /work/test3.log
-rw-r--r--. 1 root root        142  9月  8 06:30 /work/test4.sh
-rw-r--r--. 1 root root        102  9月 23 07:56 /work/test5.txt
-rw-r--r--. 1 root root        215  9月 24 06:00 /work/test5_.txt
-rw-r--r--. 1 root root        102  9月 23 07:57 /work/test5_1.txt
-rw-r--r--. 1 root root         56  9月 23 08:13 /work/test5_2.txt
-rw-r--r--. 1 root root        144  9月 23 12:40 /work/test5_3.txt
-rw-r--r--. 1 root root        102  9月 23 13:25 /work/test5_4.txt
-rw-r--r--. 1 root root         54  9月 23 13:30 /work/test5_5.txt
-rw-r--r--. 1 root root        129  9月 24 06:03 /work/test5_6.txt
-rw-r--r--. 1 root root        102  9月 25 06:07 /work/test5_7.txt
[root@test-centos7 ~]# date -r /work/test.log
2015年  9月  6日 日曜日 15:44:26 JST

5.日時を設定する

「-s」オプションを使用することで、システム日時を変更することが出来る。

20150930_000000

[root@test-centos7 ~]# date
2015年  9月 30日 水曜日 14:15:01 JST
[root@test-centos7 ~]# date -s "2015/01/01 11:00:00"
2015年  1月  1日 木曜日 11:00:00 JST
[root@test-centos7 ~]#
[root@test-centos7 ~]# date
2015年  1月  1日 木曜日 11:00:03 JST
Docker実践入門――Linuxコンテナ技術の基礎から応用まで (Software Design plus) Docker実践入門――Linuxコンテナ技術の基礎から応用まで (Software Design plus)

nkfコマンド・iconvコマンドで覚えておきたい文字コード・改行コード変換方法いろいろ

$
0
0

Linuxで日本語を含むファイルやWindowsで作成したファイルを利用する際にネックになる、文字コードや改行コード。
今回は、それらの変換で良く利用されるコマンド、nkfコマンドとiconvコマンドで覚えておくと便利な使い方についてをまとめてみる事にする。

個人的な感想としては、nkfコマンドの方が多機能なのだが、iconvコマンドの方が新しくとっつきやすい、デフォルトで用意されている事が多い印象がある。

1.文字コードの変換を行う

まずは基本の機能。文字コードを変換する場合は、以下のようにコマンドを実行する。

1-1.nfkの場合

nkfコマンドの場合は、以下のオプションを駆使して文字コード変換を行う。

ファイルの文字コードを指定する J … JIS
E … EUC-JP
S … SJIS
W … UTF-8
変換後の文字コードを指定する j … JIS
e … EUC-JP
s … SJIS
w … UTF-8

 

例えば、EUC-JPのファイルをUTF-8に変換する場合は、以下のようにコマンドを実行すれば良い。

nkf -Ew 対象ファイル

20150930_000001

[root@test-centos7 ~]# file /work/nkftest1.txt
/work/nkftest1.txt: ISO-8859 text
[root@test-centos7 ~]# cat /work/nkftest1.txt
、「、「、「、「、「、「

[root@test-centos7 ~]# nkf -Ew /work/nkftest1.txt
ああああああ

1-2.iconvの場合

iconvの場合は、以下のようにコマンドを実行することで文字コード変換を行う事が出来る。

iconv -f ファイルの文字コード -t 変換させる文字コード 対象ファイル

20151001_000000

[root@test-centos7 ~]# file /work/nkftest1.txt
/work/nkftest1.txt: ISO-8859 text
[root@test-centos7 ~]#
[root@test-centos7 ~]# iconv -f eucjp -t utf-8 /work/nkftest1.txt
ああああああ

2.改行コードの変換を行う

nkfコマンドで改行コードを変換する場合は、以下のオプションを使用して変換を行う。

-Lu unix改行形式(LF)に変換
-Lw windows改行形式(CRLF)に変換
-Lm macintosh改行形式(CR)に変換

 

なお、改行コードの変換はnkfでは可能だが、iconvでは対応していない。
nkfが入っていない場合は、別途「dos2unix」「unix2dos」コマンドで対応すると良いだろう。

3.ファイルの文字コードを確認する

ファイルの文字コードを確認する場合も、nkfコマンドで「-g」オプションを使用することで実施可能だ。
なお、nkfコマンドがない場合は「file」コマンドを使用することで文字コードを確認することが出来る。

nkf -g 対象ファイル

20151001_000001

[root@test-centos7 ~]# nkf -g /work/nkftest1.txt
EUC-JP
[root@test-centos7 ~]# nkf -g /work/nkftest2.txt
Shift_JIS
[root@test-centos7 ~]#
[root@test-centos7 ~]# file /work/nkftest1.txt
/work/nkftest1.txt: ISO-8859 text
[root@test-centos7 ~]# file /work/nkftest2.txt
/work/nkftest2.txt: Non-ISO extended-ASCII text

4.文字コード・改行コードを変換して上書き保存する

文字コード・改行コードを変換した状態で上書き保存する場合は、nkfコマンドで「–overwrite」オプションを付与すると良いだろう。

nkf -変換オプション --overwrite 対象ファイル

20151001_000002

[root@test-centos7 ~]# nkf -g /work/nkftest1.txt
EUC-JP
[root@test-centos7 ~]# nkf -s --overwrite /work/nkftest1.txt
[root@test-centos7 ~]# nkf -g /work/nkftest1.txt
Shift_JIS

以上、タイトルだとnkfとiconvと記述したが、ほとんどnkfコマンドだけだった。
最近だとnkf入ってない事も多いので、まぁ環境に合わせて使い分けて貰えれば…

文字コード「超」研究 改訂第2版 文字コード「超」研究 改訂第2版

シェルスクリプトで出力結果の桁数合わせ、スペースでの幅合わせを行う

$
0
0

先日、シェルスクリプトで出力結果をキレイに整形する必要があり、その際に出力結果の桁数合わせ、幅合わせを行う必要があったのでその備忘。
どちらも、pfintfコマンドで実現出来る。

1.桁あわせを行う場合

桁あわせを行う場合、以下のように記述する。

printf "%0桁数d\n" 数字

 

例えば、34という数字を5桁で出力させる場合は以下のようにする。

printf "%05d\n" 34

20151013_000000

[root@test-centos7 ~]# printf "%05d\n" 34
00034

2.スペースで幅合わせを行う場合

スペースでの幅合わせを行う場合、以下のように記述する。

printf "%幅数s\n" 表示文字

 

例えば、56という数字を10文字分のスペースで出力させる場合は以下のようにする。

printf "%10s\n" 56

20151013_000001

[root@test-centos7 ~]# printf "%10s\n" 56
        56

 

シェルプログラミング実用テクニック (Software Design plus) シェルプログラミング実用テクニック (Software Design plus)

Pythonによるssh自動接続用スクリプト(試作)

$
0
0

(すっごい久々にブログの記事書いた気がする…)

この度、転職が決まったんですが新しい職場だとクライアントはMacを使える事になった。
今までの職場だとTeratermのlistboxを使用したマクロでサーバにログインしてたので、似たようなものをMac用に作ることにしてみた。

で、最初bashで書こうかと思ったんだけど、勉強がてらPythonで書いてみようと思いPythonにした。
とりあえず、今の状態で出来ることとしては以下。

  • host.listを元に接続先を選択してログイン
  • suでユーザのスイッチ可
  • 操作ログの自動取得(ログ中にタイムスタンプの挿入不可)

なお、sshでの接続にはpexpectを用いているので、それだけは別途インストールが必要になる。
ログイン時に実行させる任意のコマンドをファイルに書いといたり、操作ログに操作時のタイムスタンプを挿入させたりしたいけど、まだ出来てない…どうもpexpectなどで直接ログ取得時にタイムスタンプを付与すると、コマンドの実行結果行に中途半端なタイムスタンプがついちゃったり、入力文字列の1つ1つにタイムスタンプがついて大変うざったい事になるので、scriptコマンドの時と同様に別プロセスで付与させるしかないのかな?

今のトコ、必要になるファイルはスクリプトファイル本体とhost.list(接続先ホストの情報を記述している)の2ファイルのみ。
あんまりセキュリティは考えていない…(今後の事考えるとよろしくないかも)。

1.host.list

基本的に、今までのTeratermマクロのものを使いまわせるよう、同じフォーマットとしている。

●host.list

# SSHAutoLogin.ttl用 ログインホスト設定ファイル
# 左から順に、以下の内容を記述していく。
# HOST_NAME(任意の名称。接続するホストの選択時やログ名に利用する。必須。)
# HOST_IP(ホストのIPアドレス。接続時に利用する。必須。)
# HOST_ROOT_USER(管理者ユーザ名。ログインユーザを設定してスイッチする場合はrootユーザを設定。必須。)
# HOST_ROOT_PASS(管理者ユーザパスワード。必須。)
# HOST_USER(ログインユーザ名。管理者ユーザで直接ログイン出来る場合は不要。)
# HOST_PASS(ログインユーザパスワード。管理者ユーザで直接ログイン出来る場合は不要。)
# SUDO_FLAG(スイッチ文を「sudo su -」とするか否か。何かしら(0でも1でも)入力すると有効になる。スイッチ時のコマンドが「su -」の場合は不要)

# HOST_NAME, HOST_IP, HOST_ROOT_USER, HOST_ROOT_PASS, HOST_USER, HOST_PASS, SUDO_FLAG

# CentOS(「su -」)でスイッチする例
Test-CentOS1,172.28.0.101,root,password,test,password

# CentOS(「su -」)でスイッチせずに直接ログインする例
Test-CentOS2,172.28.0.102,root,password

# Ubuntu(sudo su -)でスイッチする例
Test-Ubuntu1,172.28.0.103,test,password,test,password,1

 

本当は、Macで使うこと前提ならssh接続時に背景画像を変える事を前提に、その辺の設定を記述しても良さそうだけど、今はいいや…

2.ssh_connect.py

スクリプト本体。
あまりいい出来ではない…少しづつ直していこう。

●ssh_connect.py

#! /usr/bin/python
# -*- coding: utf-8 -*-

##################
# モジュール読込 #
##################
from __future__ import division
import curses
from math import *
import pexpect
import locale
locale.setlocale(locale.LC_ALL, "")
from datetime import datetime
import logging

########
# 関数 #
########

def ssh_connect(line_no):
    # 接続時に使用する情報を取得
    connect_host_name      = "".join(map(str,host_name_list[line_no]))
    connect_host_ip        = "".join(map(str,host_ip_list[line_no]))
    connect_host_root_user = "".join(map(str,host_root_user_list[line_no]))
    connect_host_root_pass = "".join(map(str,host_root_pass_list[line_no]))
    connect_host_user      = "".join(map(str,host_user_list[line_no]))
    connect_host_pass      = "".join(map(str,host_pass_list[line_no]))
    connect_sudo_flag      = "".join(map(str,sudo_flag_list[line_no]))

    # ログインユーザーの指定有無を確認
    if connect_host_user == "":
        connect_user = connect_host_root_user
        connect_pass = connect_host_root_pass
    else:
        connect_user = connect_host_user
        connect_pass = connect_host_pass

    foo = pexpect.spawn('ssh -o "StrictHostKeyChecking=no" %s@%s' % (connect_user, connect_host_ip))
    foo.logfile_read = open('%s%s.log.%s' % ( log_dir,connect_host_name,now_time ),"w")
    foo.expect(['.*ssword:','パスワード:'])
    print foo.before.rstrip()
    print foo.after.rstrip()
    foo.sendline(connect_pass)
    if not connect_host_user == "":
        foo.expect(['$','#'])
        print foo.before.strip()
        print foo.after.strip()
        foo.sendline('su - %s' % (connect_host_root_user))

        foo.expect(['.*ssword:','パスワード:'])
        print foo.before.strip()
        print foo.after.strip()
        foo.sendline(connect_host_root_pass)
    foo.interact()

############
# 設定関連 #
############
max_row      = 20
list_file    = '/tmp/data.csv'
command_file = ''
log_dir      = '/tmp/'
now_time     = datetime.now().strftime('%Y%m%d_%H%M%S')

##################
# curses関連設定 #
##################
# リスト表示件数
screen        = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
screen.keypad( 1 )
curses.init_pair(1,curses.COLOR_BLACK, curses.COLOR_CYAN)
highlightText = curses.color_pair( 1 )
normalText    = curses.A_NORMAL
screen.border( 0 )
curses.curs_set( 0 )
box           = curses.newwin( max_row + 2, 100, 1, 1 )
box.box()

##################
# リスト情報取得 #
##################
f = open(list_file)
line = f.readline()
i = 0
host_name_list      = []
host_ip_list        = []
host_root_user_list = []
host_root_pass_list = []
host_user_list      = []
host_pass_list      = []
sudo_flag_list      = []
while line:
    line = line.strip()
    # コメント・空行を除外
    if line.startswith( "#" ) or len( line ) == 0:
        line = f.readline()
        continue
    # リストの各要素を取得
    line_column = len( line.split(',') )
    if line_column == 4:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        host_root_user = line.split(',')[2]
        host_root_pass = line.split(',')[3]
        host_user      = ""
        host_pass      = ""
        sudo_flag      = ""
    elif line_column == 6:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        host_root_user = line.split(',')[2]
        host_root_pass = line.split(',')[3]
        host_user      = line.split(',')[4]
        host_pass      = line.split(',')[5]
        sudo_flag      = ""
    elif line_column == 7:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        host_root_user = line.split(',')[2]
        host_root_pass = line.split(',')[3]
        host_user      = line.split(',')[4]
        host_pass      = line.split(',')[5]
        sudo_flag      = line.split(',')[6]
    else:
        exit(1)
        print "リストに誤りがあります。"
        print line
    host_name_list      += [[host_name]]
    host_ip_list        += [[host_ip]]
    host_root_user_list += [[host_root_user]]
    host_root_pass_list += [[host_root_pass]]
    host_user_list      += [[host_user]]
    host_pass_list      += [[host_pass]]
    sudo_flag_list      += [[sudo_flag]]
    line = f.readline()
f.close
row_num = len( host_name_list )

##############
# リスト表示 #
##############
pages = int( ceil( row_num / max_row ) )
position = 1
page = 1
for i in range( 1, max_row + 1 ):
    if row_num == 0:
        box.addstr( 1, 1, "There aren't host_name_list", highlightText )
    else:
        if (i == position):
            box.addstr( i, 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), highlightText )
        else:
            box.addstr( i, 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), normalText )
        if i == row_num:
            break
screen.refresh()
box.refresh()

##########################
# ホスト選択画面キー操作 #
##########################
x = screen.getch()
while x != 27:

    # 下キー押下時の動作
    if x == curses.KEY_DOWN:
        if page == 1:
            if position < i:
                 position = position + 1
             else:
                 if pages > 1:
                    page = page + 1
                    position = 1 + ( max_row * ( page - 1 ) )
        elif page == pages:
            if position < row_num:
                position = position + 1
        else:
            if position < max_row + ( max_row * ( page - 1 ) ):
                 position = position + 1
             else:
                 page = page + 1
                 position = 1 + ( max_row * ( page - 1 ) )
     # 上キー押下時の動作
     if x == curses.KEY_UP:
         if page == 1:
             if position > 1:
                position = position - 1
        else:
            if position > ( 1 + ( max_row * ( page - 1 ) ) ):
                position = position - 1
            else:
                page = page - 1
                position = max_row + ( max_row * ( page - 1 ) )

    # 左キー押下時の動作
    if x == curses.KEY_LEFT:
        if page > 1:
            page = page - 1
            position = 1 + ( max_row * ( page - 1 ) )

    # 右キー押下時の動作
    if x == curses.KEY_RIGHT:
        if page < pages:
            page = page + 1
            position = ( 1 + ( max_row * ( page - 1 ) ) )

    # Enter押下時(決定)の処理
    if x == ord( "\n" ) and row_num != 0:
        screen.erase()
        screen.border( 0 )

        curses.endwin()
        ssh_connect(position - 1)
        exit()

    box.erase()
    screen.border( 0 )
    box.border( 0 )

    for i in range( 1 + ( max_row * ( page - 1 ) ), max_row + 1 + ( max_row * ( page - 1 ) ) ):
        if row_num == 0:
            box.addstr( 1, 1, "There aren't host_name_list",  highlightText )
        else:
            if ( i + ( max_row * ( page - 1 ) ) == position + ( max_row * ( page - 1 ) ) ):
                box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), highlightText )
            else:
                box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), normalText )
            if i == row_num:
                break

    screen.refresh()
    box.refresh()
    x = screen.getch()

curses.endwin()
exit()

 

実際に使用した際のイメージがこちら
コマンドを実行すると…

スクリーンショット 2015-11-06 22.30.16

 

接続先のリストが表示されるので、接続するホストを矢印キーで選択しEnter。

スクリーンショット 2015-11-06 22.30.29

 

ログイン完了。
rootにスイッチする場合は、host.listで指定してればスイッチするようにしている。

スクリーンショット 2015-11-06 22.30.40

 

まぁ、これからある程度使っていくだろうし、少しづつブラッシュアップしていこう。

サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考 サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考

Pythonによるssh自動接続用スクリプト(試作) 鍵認証ログイン対応

$
0
0

先日作成したssh自動接続用のスクリプト、基本的にパスワード認証のみで考えていたのだけどAWSとかAzureだと鍵認証なんだよね。
という訳で、微修正ながら鍵認証に対応させてみた。

1.host.list

host.listには、鍵ファイルの指定列を新しく追加した。

●host.list

# SSHAutoLogin.ttl用 ログインホスト設定ファイル
# 左から順に、以下の内容を記述していく。
# HOST_NAME(任意の名称。接続するホストの選択時やログ名に利用する。必須。)
# HOST_IP(ホストのIPアドレス。接続時に利用する。必須。)
# KEY_FILE(鍵ファイルの設置PATH。ない場合は空欄で記述。)
# HOST_ROOT_USER(管理者ユーザ名。ログインユーザを設定してスイッチする場合はrootユーザを設定。必須。)
# HOST_ROOT_PASS(管理者ユーザパスワード。必須。)
# HOST_USER(ログインユーザ名。管理者ユーザで直接ログイン出来る場合は不要。)
# HOST_PASS(ログインユーザパスワード。管理者ユーザで直接ログイン出来る場合は不要。)
# SUDO_FLAG(スイッチ文を「sudo su -」とするか否か。何かしら(0でも1でも)入力すると有効になる。スイッチ時のコマンドが「su -」の場合は不要)

# HOST_NAME, HOST_IP, HOST_ROOT_USER, HOST_ROOT_PASS, HOST_USER, HOST_PASS, SUDO_FLAG

# CentOS(「su -」)でスイッチする例
Test-CentOS1,172.28.0.101,,root,password,test,password

# CentOS(「su -」)でスイッチせずに直接ログインする例
Test-CentOS2,172.28.0.102,,root,password

# Ubuntu(sudo su -)でスイッチする例
Test-Ubuntu1,172.28.0.103,,test,password,test,password,1

# AWSテスト
AWSテスト,XXX.XXX.XXX.XXX,/tmp/test.pem,centos,

2.ssh_connect.py

スクリプト本体。
まぁ、ちょっとだけ微修正しただけだけど…

●ssh_connect.py

#! /usr/bin/python
# -*- coding: utf-8 -*-
# +-------------------------------------------+
# +                                           +
# +                                           +
# +-------------------------------------------+

##################
# モジュール読込 #
##################
from __future__ import division
import curses
from math import *
import pexpect
import locale
locale.setlocale(locale.LC_ALL, "")
from datetime import datetime
import logging

########
# 関数 #
########

def ssh_connect(line_no):
    # 接続時に使用する情報を取得
    connect_host_name      = "".join(map(str,host_name_list[line_no]))
    connect_host_ip        = "".join(map(str,host_ip_list[line_no]))
    connect_key_file       = "".join(map(str,key_file_list[line_no]))
    connect_host_root_user = "".join(map(str,host_root_user_list[line_no]))
    connect_host_root_pass = "".join(map(str,host_root_pass_list[line_no]))
    connect_host_user      = "".join(map(str,host_user_list[line_no]))
    connect_host_pass      = "".join(map(str,host_pass_list[line_no]))
    connect_sudo_flag      = "".join(map(str,sudo_flag_list[line_no]))

    # ログインユーザーの指定有無を確認
    if connect_host_user == "":
        connect_user = connect_host_root_user
        connect_pass = connect_host_root_pass
    else:
        connect_user = connect_host_user
        connect_pass = connect_host_pass

    if connect_key_file == "":
        foo = pexpect.spawn('ssh -o "StrictHostKeyChecking=no" %s@%s' % (connect_user, connect_host_ip))
    else:
        foo = pexpect.spawn('ssh -o "StrictHostKeyChecking=no" -i %s %s@%s' % (connect_key_file, connect_user, connect_host_ip))

    foo.logfile_read = open('%s%s.log.%s' % ( log_dir,connect_host_name,now_time ),"w")
    if not connect_pass == "":
        foo.expect(['.*ssword:','パスワード:'])
        print foo.before.rstrip()
        print foo.after.rstrip()
        foo.sendline(connect_pass)
    if not connect_host_user == "":
        foo.expect(['$','#'])
        print foo.before.strip()
        print foo.after.strip()
        foo.sendline('su - %s' % (connect_host_root_user))

        foo.expect(['.*ssword:','パスワード:'])
        print foo.before.strip()
        print foo.after.strip()
        foo.sendline(connect_host_root_pass)
    foo.interact()


############
# 設定関連 #
############
max_row      = 20
list_file    = '/tmp/data.csv'
command_file = ''
log_dir      = '/tmp/'
now_time     = datetime.now().strftime('%Y%m%d_%H%M%S')

##################
# curses関連設定 #
##################
# リスト表示件数
screen        = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
screen.keypad( 1 )
curses.init_pair(1,curses.COLOR_BLACK, curses.COLOR_CYAN)
highlightText = curses.color_pair( 1 )
normalText    = curses.A_NORMAL
screen.border( 0 )
curses.curs_set( 0 )
box           = curses.newwin( max_row + 2, 100, 1, 1 )
box.box()


##################
# リスト情報取得 #
##################
f = open(list_file)
line = f.readline()
i = 0
host_name_list      = []
host_ip_list        = []
key_file_list       = []
host_root_user_list = []
host_root_pass_list = []
host_user_list      = []
host_pass_list      = []
sudo_flag_list      = []
while line:
    line = line.strip()
    # コメント・空行を除外
    if line.startswith( "#" ) or len( line ) == 0:
        line = f.readline()
        continue
    # リストの各要素を取得
    line_column = len( line.split(',') )
    if line_column == 5:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        key_file       = line.split(',')[2]
        host_root_user = line.split(',')[3]
        host_root_pass = line.split(',')[4]
        host_user      = ""
        host_pass      = ""
        sudo_flag      = ""
    elif line_column == 7:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        key_file       = line.split(',')[2]
        host_root_user = line.split(',')[3]
        host_root_pass = line.split(',')[4]
        host_user      = line.split(',')[5]
        host_pass      = line.split(',')[6]
        sudo_flag      = ""
    elif line_column == 8:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        key_file       = line.split(',')[2]
        host_root_user = line.split(',')[3]
        host_root_pass = line.split(',')[4]
        host_user      = line.split(',')[5]
        host_pass      = line.split(',')[6]
        sudo_flag      = line.split(',')[7]
    else:
        curses.endwin()
        print "リストに誤りがあります。"
        print line
        exit(1)
    host_name_list      += [[host_name]]
    host_ip_list        += [[host_ip]]
    key_file_list       += [[key_file]]
    host_root_user_list += [[host_root_user]]
    host_root_pass_list += [[host_root_pass]]
    host_user_list      += [[host_user]]
    host_pass_list      += [[host_pass]]
    sudo_flag_list      += [[sudo_flag]]
    line = f.readline()
f.close
row_num = len( host_name_list )


##############
# リスト表示 #
##############
pages = int( ceil( row_num / max_row ) )
position = 1
page = 1
for i in range( 1, max_row + 1 ):
    if row_num == 0:
        box.addstr( 1, 1, "There aren't host_name_list", highlightText )
    else:
        if (i == position):
            box.addstr( i, 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), highlightText )
        else:
            box.addstr( i, 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), normalText )
        if i == row_num:
            break
screen.refresh()
box.refresh()


##########################
# ホスト選択画面キー操作 #
##########################
x = screen.getch()
while x != 27:

    # 下キー押下時の動作
    if x == curses.KEY_DOWN:
        if page == 1:
            if position < i:
                 position = position + 1
             else:
                 if pages > 1:
                    page = page + 1
                    position = 1 + ( max_row * ( page - 1 ) )
        elif page == pages:
            if position < row_num:
                position = position + 1
        else:
            if position < max_row + ( max_row * ( page - 1 ) ):
                 position = position + 1
             else:
                 page = page + 1
                 position = 1 + ( max_row * ( page - 1 ) )
     # 上キー押下時の動作
     if x == curses.KEY_UP:
         if page == 1:
             if position > 1:
                position = position - 1
        else:
            if position > ( 1 + ( max_row * ( page - 1 ) ) ):
                position = position - 1
            else:
                page = page - 1
                position = max_row + ( max_row * ( page - 1 ) )

    # 左キー押下時の動作
    if x == curses.KEY_LEFT:
        if page > 1:
            page = page - 1
            position = 1 + ( max_row * ( page - 1 ) )

    # 右キー押下時の動作
    if x == curses.KEY_RIGHT:
        if page < pages:
            page = page + 1
            position = ( 1 + ( max_row * ( page - 1 ) ) )

    # Enter押下時(決定)の処理
    if x == ord( "\n" ) and row_num != 0:
        screen.erase()
        screen.border( 0 )

        curses.endwin()
        ssh_connect(position - 1)
        exit()

    box.erase()
    screen.border( 0 )
    box.border( 0 )

    for i in range( 1 + ( max_row * ( page - 1 ) ), max_row + 1 + ( max_row * ( page - 1 ) ) ):
        if row_num == 0:
            box.addstr( 1, 1, "There aren't host_name_list",  highlightText )
        else:
            if ( i + ( max_row * ( page - 1 ) ) == position + ( max_row * ( page - 1 ) ) ):
                box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), highlightText )
            else:
                box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), normalText )
            if i == row_num:
                break

    screen.refresh()
    box.refresh()
    x = screen.getch()

curses.endwin()
exit()
プログラミング超初心者が初心者になるためのPython入門(1) セットアップ・文字列・数値編 プログラミング超初心者が初心者になるためのPython入門(1) セットアップ・文字列・数値編

cp/mvコマンドで、配置先に同名のファイルがあった場合のみリネームして配置させる

$
0
0

Windowsのエクスプローラーでコピーをすると、同名のファイルがあった場合には以下のような画面が表示される。
その時に表示される選択肢である「コピーするが両方のファイルを保持する」とほぼ同等の動作をLinuxのcp/mvコマンドで実現する場合、どうすればいいのだろう?

20151112_000000

 

厳密な動作は少々異なるが、これらをcp/mvコマンドで実現する場合は「–backup」オプションを付与し、その際の動作を指定する事で実現可能だ。
例えば、連番の場合は以下のようにする。

cp --backup=t コピー元 コピー先
mv --backup=t 移動元 移動先

20151112_000002

[root@test-centos7 ~]# ls -l /work7
合計 0
[root@test-centos7 ~]# ls -la /work/test.txt
-rw-r--r--. 1 root root 108  7月  7 20:09 /work/test.txt
[root@test-centos7 ~]#
[root@test-centos7 ~]# # ファイルをコピー(同名ファイル無し)
[root@test-centos7 ~]# \cp --backup=t /work/test.txt /work7
[root@test-centos7 ~]#
[root@test-centos7 ~]# ls -l /work7
合計 4
-rw-r--r--. 1 root root 108 11月 12 05:12 test.txt
[root@test-centos7 ~]#
[root@test-centos7 ~]# ls -l /work/test.py
-rw-r--r--. 1 root root 2223 10月 27 07:10 /work/test.py
[root@test-centos7 ~]#
[root@test-centos7 ~]# # ファイルをコピー(同名ファイル有り)
[root@test-centos7 ~]# \cp --backup=t /work/test.py /work7/test.txt
[root@test-centos7 ~]#
[root@test-centos7 ~]# ls -l /work7
合計 8
-rw-r--r--. 1 root root 2223 11月 12 05:13 test.txt
-rw-r--r--. 1 root root  108 11月 12 05:12 test.txt.~1~
[root@test-centos7 ~]#
[root@test-centos7 ~]# # mvでも同等の処理が出来る
[root@test-centos7 ~]# ls -l /work/test.rc
-rw-r--r--. 1 root root 2590 10月 28 21:31 /work/test.rc
[root@test-centos7 ~]# \mv --backup=t /work/test.rc /work7/test.txt
[root@test-centos7 ~]# ls -l /work7
合計 12
-rw-r--r--. 1 root root 2590 10月 28 21:31 test.txt
-rw-r--r--. 1 root root  108 11月 12 05:12 test.txt.~1~
-rw-r--r--. 1 root root 2223 11月 12 05:13 test.txt.~2~
[root@test-centos7 ~]# ls -l /work/test.rc
ls: /work/test.rc にアクセスできません: そのようなファイルやディレクトリはありません

 

ファイル名末尾にタイムスタンプを付与する場合は以下のようにする。

cp --backup --suffix=.$(date +%Y%m%d_%H%M%S) コピー元 コピー先
mv --backup --suffix=.$(date +%Y%m%d_%H%M%S) 移動元 移動先

 

こちらの場合、コピー先の既存ファイル名を変更する(上書きする既存のファイル名をバックアップする)という動作のため、厳密な動きはWindowsの動作とは異なっているが、代替手段としては使えるのではないだろうか?

Microsoft Windows 10 Professional (32bit/64bit 日本語版 USBフラッシュドライブ) Microsoft Windows 10 Professional (32bit/64bit 日本語版 USBフラッシュドライブ)

Pythonによるssh自動接続用スクリプト(試作) タイムスタンプ付きログ取得対応版

$
0
0

先日から作成しているPythonでの選択肢型ssh自動接続スクリプト、なんとかタイムスタンプ付きのログを取得出来るよう改良した。
まぁ、一時ファイルを作成してタイムスタンプを付与、しかもtailのラッパースクリプトとして動作させているので、あまり納得はいってないんだけど…一応動くし、まぁいいか。どうせMacかLinuxでしか動かさないし。

1.host.list

host.listについては、前回作成した内容から変わらない。

●host.list

# SSHAutoLogin.ttl用 ログインホスト設定ファイル
# 左から順に、以下の内容を記述していく。
# HOST_NAME(任意の名称。接続するホストの選択時やログ名に利用する。必須。)
# HOST_IP(ホストのIPアドレス。接続時に利用する。必須。)
# KEY_FILE(鍵ファイルの設置PATH。ない場合は空欄で記述。)
# HOST_ROOT_USER(管理者ユーザ名。ログインユーザを設定してスイッチする場合はrootユーザを設定。必須。)
# HOST_ROOT_PASS(管理者ユーザパスワード。必須。)
# HOST_USER(ログインユーザ名。管理者ユーザで直接ログイン出来る場合は不要。)
# HOST_PASS(ログインユーザパスワード。管理者ユーザで直接ログイン出来る場合は不要。)
# SUDO_FLAG(スイッチ文を「sudo su -」とするか否か。何かしら(0でも1でも)入力すると有効になる。スイッチ時のコマンドが「su -」の場合は不要)

# HOST_NAME, HOST_IP, KEY_FILE, HOST_ROOT_USER, HOST_ROOT_PASS, HOST_USER, HOST_PASS, SUDO_FLAG

# CentOS(「su -」)でスイッチする例
Test-CentOS1,172.28.0.101,,root,password,test,password

# CentOS(「su -」)でスイッチせずに直接ログインする例
Test-CentOS2,172.28.0.102,,root,password

# Ubuntu(sudo su -)でスイッチする例
Test-Ubuntu1,172.28.0.103,,test,password,test,password,1

# AWSテスト
AWSテスト,XXX.XXX.XXX.XXX,/tmp/test.pem,centos,

2.ssh_connect.py

ssh_connect.pyについては、Teratermログのようなタイムスタンプ付きのログを取得させるようにした。

●ssh_connect.py

#! /usr/bin/python
# -*- coding: utf-8 -*-
# +-------------------------------------------+
# +                                           +
# +                                           +
# +-------------------------------------------+

##################
# モジュール読込 #
##################
from __future__ import division  #You don't need this in Python3
import curses
from math import *
import os
import pexpect
import locale
locale.setlocale(locale.LC_ALL, "")
from datetime import datetime
import subprocess

########
# 関数 #
########

def ssh_connect(line_no):
    # 接続時に使用する情報を取得
    connect_host_name      = "".join(map(str,host_name_list[line_no]))
    connect_host_ip        = "".join(map(str,host_ip_list[line_no]))
    connect_key_file       = "".join(map(str,key_file_list[line_no]))
    connect_host_root_user = "".join(map(str,host_root_user_list[line_no]))
    connect_host_root_pass = "".join(map(str,host_root_pass_list[line_no]))
    connect_host_user      = "".join(map(str,host_user_list[line_no]))
    connect_host_pass      = "".join(map(str,host_pass_list[line_no]))
    connect_sudo_flag      = "".join(map(str,sudo_flag_list[line_no]))

    # 一時ログファイル、正規ログファイル定義
    pid          = str(os.getpid())
    tmp_log      = tmp_dir + '.' + pid + '.' + connect_host_name + '.' + now_time
    terminal_log = log_dir + now_time + '_' + connect_host_name + '.log'

    # ログインユーザーの指定有無を確認
    if connect_host_user == "":
        connect_user = connect_host_root_user
        connect_pass = connect_host_root_pass
    else:
        connect_user = connect_host_user
        connect_pass = connect_host_pass
    if connect_key_file == "":
        foo = pexpect.spawn('ssh -o "StrictHostKeyChecking=no" %s@%s' % (connect_user, connect_host_ip))
    else:
        foo = pexpect.spawn('ssh -o "StrictHostKeyChecking=no" -i %s %s@%s' % (connect_key_file, connect_user, connect_host_ip))

    # ログの取得開始
    foo.logfile_read = open(tmp_log,"w")

    log_tail = 'tail -f ' + tmp_log
    log_awk  = 'gawk \'{ print strftime("[%Y/%m/%d %H:%M:%S]") " " $0 } {system (" ")}\' >' + terminal_log

    get_log_command  = log_tail + ' | ' + log_awk + ' &'
    #subprocess.Popen(get_log_command, shell=True)
    os.system(get_log_command)

    if not connect_pass == "":
        foo.expect(['.*ssword:','パスワード:'])
        print foo.before.rstrip()
        print foo.after.rstrip()
        foo.sendline(connect_pass)
    if not connect_host_user == "":
        foo.expect(['$','#'])
        print foo.before.strip()
        print foo.after.strip()
        foo.sendline('su - %s' % (connect_host_root_user))

        foo.expect(['.*ssword:','パスワード:'])
        print foo.before.strip()
        print foo.after.strip()
        foo.sendline(connect_host_root_pass)
    foo.interact()
    #os.system('kill ' + log_pid + ' &')
    os.system('ps -fC "tail" | grep "' + log_tail + '" | awk \'{ print $2\'} | xargs kill')
    os.remove(tmp_log)

############
# 設定関連 #
############
max_row      = 20
list_file    = '/root/data.csv'
command_file = ''
log_dir      = '/work/'
tmp_dir      = '/tmp/'
now_time     = datetime.now().strftime('%Y%m%d_%H%M%S')

##################
# curses関連設定 #
##################
# リスト表示件数
screen        = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
screen.keypad( 1 )
curses.init_pair(1,curses.COLOR_BLACK, curses.COLOR_CYAN)
highlightText = curses.color_pair( 1 )
normalText    = curses.A_NORMAL
screen.border( 0 )
curses.curs_set( 0 )
box           = curses.newwin( max_row + 2, 100, 1, 1 )
box.box()

##################
# リスト情報取得 #
##################
f = open(list_file)
line = f.readline()
i = 0
host_name_list      = []
host_ip_list        = []
key_file_list       = []
host_root_user_list = []
host_root_pass_list = []
host_user_list      = []
host_pass_list      = []
sudo_flag_list      = []
while line:
    line = line.strip()
    # コメント・空行を除外
    if line.startswith( "#" ) or len( line ) == 0:
        line = f.readline()
        continue
    # リストの各要素を取得
    line_column = len( line.split(',') )
    if line_column == 5:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        key_file       = line.split(',')[2]
        host_root_user = line.split(',')[3]
        host_root_pass = line.split(',')[4]
        host_user      = ""
        host_pass      = ""
        sudo_flag      = ""
    elif line_column == 7:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        key_file       = line.split(',')[2]
        host_root_user = line.split(',')[3]
        host_root_pass = line.split(',')[4]
        host_user      = line.split(',')[5]
        host_pass      = line.split(',')[6]
        sudo_flag      = ""
    elif line_column == 8:
        host_name      = line.split(',')[0]
        host_ip        = line.split(',')[1]
        key_file       = line.split(',')[2]
        host_root_user = line.split(',')[3]
        host_root_pass = line.split(',')[4]
        host_user      = line.split(',')[5]
        host_pass      = line.split(',')[6]
        sudo_flag      = line.split(',')[7]
    else:
        curses.endwin()
        print "リストに誤りがあります。"
        print line
        exit(1)
    host_name_list      += [[host_name]]
    host_ip_list        += [[host_ip]]
    key_file_list       += [[key_file]]
    host_root_user_list += [[host_root_user]]
    host_root_pass_list += [[host_root_pass]]
    host_user_list      += [[host_user]]
    host_pass_list      += [[host_pass]]
    sudo_flag_list      += [[sudo_flag]]
    line = f.readline()
f.close
row_num = len( host_name_list )

##############
# リスト表示 #
##############
pages = int( ceil( row_num / max_row ) )
position = 1
page = 1
for i in range( 1, max_row + 1 ):
    if row_num == 0:
        box.addstr( 1, 1, "There aren't host_name_list", highlightText )
    else:
        if (i == position):
            box.addstr( i, 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), highlightText )
        else:
            box.addstr( i, 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), normalText )
        if i == row_num:
            break
screen.refresh()
box.refresh()

##########################
# ホスト選択画面キー操作 #
##########################
x = screen.getch()
while x != 27:

    # 下キー押下時の動作
    if x == curses.KEY_DOWN:
        if page == 1:
            if position < i:
                 position = position + 1
             else:
                 if pages > 1:
                    page = page + 1
                    position = 1 + ( max_row * ( page - 1 ) )
        elif page == pages:
            if position < row_num:
                position = position + 1
        else:
            if position < max_row + ( max_row * ( page - 1 ) ):
                 position = position + 1
             else:
                 page = page + 1
                 position = 1 + ( max_row * ( page - 1 ) )
     # 上キー押下時の動作
     if x == curses.KEY_UP:
         if page == 1:
             if position > 1:
                position = position - 1
        else:
            if position > ( 1 + ( max_row * ( page - 1 ) ) ):
                position = position - 1
            else:
                page = page - 1
                position = max_row + ( max_row * ( page - 1 ) )

    # 左キー押下時の動作
    if x == curses.KEY_LEFT:
        if page > 1:
            page = page - 1
            position = 1 + ( max_row * ( page - 1 ) )

    # 右キー押下時の動作
    if x == curses.KEY_RIGHT:
        if page < pages:
            page = page + 1
            position = ( 1 + ( max_row * ( page - 1 ) ) )

    # Enter押下時(決定)の処理
    if x == ord( "\n" ) and row_num != 0:
        screen.erase()
        screen.border( 0 )

        curses.endwin()
        ssh_connect(position - 1)
        exit()

    box.erase()
    screen.border( 0 )
    box.border( 0 )

    for i in range( 1 + ( max_row * ( page - 1 ) ), max_row + 1 + ( max_row * ( page - 1 ) ) ):
        if row_num == 0:
            box.addstr( 1, 1, "There aren't host_name_list",  highlightText )
        else:
            if ( i + ( max_row * ( page - 1 ) ) == position + ( max_row * ( page - 1 ) ) ):
                box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), highlightText )
            else:
                box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + "".join(map(str,host_name_list[ i - 1 ])), normalText )
            if i == row_num:
                break

    screen.refresh()
    box.refresh()
    x = screen.getch()

curses.endwin()
exit()

 

うーん、処理の仕方が汚いのが気になるけど、とりあえずはこれでいいか…
そのうち直そう。

ハイパフォーマンスPython ハイパフォーマンスPython

tarでアーカイブ作成時に特定のディレクトリ・ファイルを除外する

$
0
0

tarでアーカイブを作成する際、ディレクトリを指定してその配下全てをアーカイブ化することが多いだろう。
その中で、特定のサブディレクトリのみ除外してアーカイブを作成する場合は、「–exclude」オプションもしくは「-X」オプションを付与すると良いだろう。

1.「–exclude」オプション

コマンドラインで直接PATHを指定する場合は、「–exclude」オプションを付与する。

tar cvf --exclude 除外ディレクトリのPATH アーカイブ対象ディレクトリ

20151112_000003

[root@test-centos7 ~]# find /work8 -type d
/work8
/work8/work8-1
/work8/work8-1/8-1-2
/work8/work8-1/8-1-3
/work8/work8-1/8-1-4
/work8/work8-2
/work8/work8-2/8-2-4
/work8/work8-2/8-2-2
/work8/work8-3
/work8/work8-4
/work8/work8-4/8-4-2
/work8/work8-4/8-4-1
/work8/work8-4/8-4-7
/work8/work8-5
/work8/work8-6
[root@test-centos7 ~]# tar czvf /tmp/test8.tar.gz --exclude /work8/work8-1 /work8
tar: メンバ名から先頭の `/' を取り除きます
/work8/
/work8/work8-2/
/work8/work8-2/8-2-4/
/work8/work8-2/8-2-2/
/work8/work8-3/
/work8/work8-4/
/work8/work8-4/8-4-2/
/work8/work8-4/8-4-1/
/work8/work8-4/8-4-7/
/work8/work8-5/
/work8/work8-6/

 

なお、複数ディレクトリを除外する場合は「–exclude」を別途記述して指定する必要がある。

20151112_000004

[root@test-centos7 ~]# tar czvf /tmp/test8.tar.gz --exclude /work8/work8-1 --exclude /work8/work8-2 /work8
tar: メンバ名から先頭の `/' を取り除きます
/work8/
/work8/work8-3/
/work8/work8-4/
/work8/work8-4/8-4-2/
/work8/work8-4/8-4-1/
/work8/work8-4/8-4-7/
/work8/work8-5/
/work8/work8-6/

2.「-X」オプション

「-X」オプションを使用すると、ファイルに記述されているPATHを除外してアーカイブファイルを作成することが出来る。

tar cvf -X 除外ディレクトリのPATHを書いたファイル アーカイブ対象ディレクトリ

20151112_000005

[root@test-centos7 ~]# cat /tmp/work8.list
/work8/work8-4
/work8/work8-5

[root@test-centos7 ~]# tar czvf /tmp/test8.tar.gz -X /tmp/work8.list /work8
tar: メンバ名から先頭の `/' を取り除きます
/work8/
/work8/work8-1/
/work8/work8-1/8-1-2/
/work8/work8-1/8-1-3/
/work8/work8-1/8-1-4/
/work8/work8-2/
/work8/work8-2/8-2-4/
/work8/work8-2/8-2-2/
/work8/work8-3/
/work8/work8-6/

 

新しいLinuxの教科書 新しいLinuxの教科書

ApacheのリバースプロキシサーバでバックのWEBサーバをまとめてBasic認証をさせる

$
0
0

少し前に、今いるプロジェクトでApacheによるリバースプロキシでのBasic認証を設定する事があったので、その備忘。
ApacheのProxyでBasic認証を処理させる場合は、以下の例ようにhttpd.conf(というか、最近ではそれをIncludeしている設定ファイル)で記述してあげればいい。

●httpd.conf(VirtualHost配下で指定している)

<VirtualHost*:80>
    ...
    <Proxy>
        AuthType Basic
        AuthName "..."
        Order deny,allow
        Allow from all
        ...
    </Proxy>    
    ...
<VirtualHost*:80>

 

できるPRO Apache Webサーバー 改訂版 Version 2.4/2.2/2.0対応 (できるPROシリーズ) できるPRO Apache Webサーバー 改訂版 Version 2.4/2.2/2.0対応 (できるPROシリーズ)

シェルスクリプトで日付が月末日かどうかを判定する

$
0
0

時折、ログのアーカイブなどで当日が月末か否かでスクリプトの処理を変えさせる必要があったりする。
シェルスクリプトで対象の日付が月末か否かを判断させる場合、以下のようにすると良いだろう。

get_date=`date +%d -d '1 day'`
if [ $get_date = "01" ];then
    echo "月末です"
fi

 

まぁ、単純にdateコマンドで日だけを取得して1日足して、その値が”01″であれば月末であることを把握するという内容。
同様に、当日が月初か否かもこれで取得出来る。

UNIXシェルスクリプト マスターピース132 UNIXシェルスクリプト マスターピース132

ncコマンドを使って、ミドルウェアのインストール前に疎通確認を行えるようにする

$
0
0

Linuxサーバで、ミドルウェアインストール前にネットワークの疎通確認を行う場合、ncコマンドが入っていれば簡易的なTCP/UDPサーバを立ち上げてポートを開けて確認を行う事が出来る。

TCPの場合は、待受側で以下のようにコマンドを実行する。

nc -vkl ポート番号

UDPの場合、keepaliveオプションが無いため、catを使って無理やり受信を続けさせる。
そのため、待受側では以下のようにコマンドを実行する。

nc -e /bin/cat -kuvl ポート番号

 

これで簡易TCP/UDPサーバが出来上がった。
送信側は、echoと組み合わせ文字列を送信させる事でテスト出来る。

echo "test" | nc IPアドレス ポート番号 #TCP側テスト
echo "test" | nc -u IPアドレス ポート番号 #UDP側テスト
ネットワークエンジニアの教科書 ネットワークエンジニアの教科書

nc(netcat)コマンドで覚えておきたい使い方8個

$
0
0

Linuxでポートの疎通確認を行う際によく用いるncコマンド。
今回は、このncコマンドで覚えておきたい使い方についてまとめてみる事にする。

使用したのは、Ubuntu 14.04 LTSに入っている以下のもの。

20151116_000001

test@test-vm-ubuntu:~$ nc --help
nc: invalid option -- '-'
This is nc from the netcat-openbsd package. An alternative nc is available
in the netcat-traditional package.
usage: nc [-46bCDdhjklnrStUuvZz] [-I length] [-i interval] [-O length]
          [-P proxy_username] [-p source_port] [-q seconds] [-s source]
          [-T toskeyword] [-V rtable] [-w timeout] [-X proxy_protocol]
          [-x proxy_address[:port]] [destination] [port]

 

1.基本的な使い方・クライアントとして動作させる

ncコマンドで最もよく使われる使い方としては、対象ホストに対してポート指定をして、クライアントとして疎通確認を行うというものだろう。
基本的には、以下のようにコマンドを実行する。

nc 対象ホスト(IPアドレス等) ポート番号

TCPではなく、UDPでの疎通を確認する場合は「-u」オプションを付与する。

nc -u 対象ホスト(IPアドレス等) ポート番号

 

ただポート確認を行うだけではなく、ヘッダを相手先ポートに送りつける事でその後の処理を実施させることも出来る。
例えば、以下のようにコマンドを実行することでwebサーバへhttp-getリクエストを行う事ができる。

echo -en "GET / HTTP/1.1\n\n" | nc 対象ホスト(IPアドレス等) 80

 

 

2.基本的な使い方・サーバとして動作させる

ncでポートの待受側(サーバ側)として動作させる場合は、以下のように「-l」オプションを付与する。

nc -l ポート番号 # TCPのポート番号で待ち受ける
nc -ul ポート番号 # UDPのポート番号で 待ち受ける

 

ただし、上記のコマンドだと一度疎通に成功するとサーバ側のプロセスが終了してしまう。
サーバ側で明示的にプロセスを終了するまでポートを開けさせたい場合は、TCPの場合は「-k」を、UDPの場合は「-e ‘cat’」でポートを開けさせておく事が出来る。

nc -kvl ポート番号 #TCP
nc -e /bin/cat -uvl ポート番号 # UDP

 

なお、CentOSやUbuntuのパッケージからインストールしたり、バンドルされているコマンドの場合、「-e」オプションが利用出来ないようにしてる可能性がある。
この場合は、別途ソースからインストールして-eオプションを使えるようにしてあげる必要があるので注意。

 

3.ファイルを転送する

ncコマンドでは、FTPやscpを使わずにクライアント⇔サーバ間で直接ファイルを転送することも出来る。
(セキュリティ考慮する必要がある環境ではおすすめしないけど)

 

●サーバ側からクライアント側にファイルを取得させる場合

nc -l ポート番号 < 転送するファイルPATH # サーバ側
nc 対象ホスト(IPアドレス等) ポート番号 > 転送されたファイルを取得するPATH # クライアント側

 

画像は、左がサーバ側、右がクライアント側のコンソール。
サーバ側でリダイレクトしてたアーカイブファイルが、無事クライアント側で取得、展開出来ている事がわかる。

20151116_000003

 

●クライアント側からサーバ側にファイルを取得させる場合

nc -l ポート番号 > 取得したファイルの保持先PATH # サーバ側
nc 対象ホスト(IPアドレス等) ポート番号 < 転送するファイルPATH # クライアント側

4.IPv4、IPv6を指定する

IPv4の場合は「-4」、IPv6の場合は「-6」を付与することで通信を可能にする。
なお、デフォルトはIPv4。

20151116_000004

test@test-vm-ubuntu:~$ # オプション無し
test@test-vm-ubuntu:~$ nc -l 55551 &
[2] 6013
test@test-vm-ubuntu:~$
test@test-vm-ubuntu:~$ # IPv4
test@test-vm-ubuntu:~$ nc -l4 55552 &
[3] 6014
test@test-vm-ubuntu:~$
test@test-vm-ubuntu:~$ # IPv6
test@test-vm-ubuntu:~$ nc -l6 55553 &
[4] 6015
test@test-vm-ubuntu:~$
test@test-vm-ubuntu:~$ netstat -an | grep 5555[1-3]
tcp        0      0 0.0.0.0:55551           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:55552           0.0.0.0:*               LISTEN
tcp6       0      0 :::55553                :::*                    LISTEN

 

5.通信の詳細を取得する

通信の詳細を表示させる場合は「-v」オプションを付与する。

 

6.ソースアドレス・ポートを指定する

パケット送信側のホストに割り当てられているIPアドレスであれば、「-s」でアドレスを指定して通信を行わせる事も出来る。
送信側のポートを指定する場合は、「-p」で指定できる。

nc -s ホストに割り当てられているIPアドレス -p 送信時のポート番号 対象ホスト ポート番号

 

7.ポート範囲を指定してスキャンを行う

nc(netcat)には、「-z」というポートの確認だけをするオプションが存在する。
これと「-v」オプションを組み合わせる事で、対象ホストでListenしているポートを確認することが出来る。

nc -vz 対象ホスト ポート番号-ポート番号

 

以下の例は、対象のホストで4440-4450の範囲で開いているポートを確認している。

20151116_000005

 

8.ポートへのアクセス時にコマンド(bash等)が実行されるようにする

「-e」オプションを使用することにより、サーバ側で特定のコマンドを実行させることが出来る。
なお、セキュリティの観点からか、UbuntuやCentOSでパッケージからインストールしたコマンドだとこのオプションは使えない。そのため、別途ソースからインストールするなどが必要となる。

nc -l -e 'コマンド' ポート番号

以下の例では、右のサーバ側でbashを待ち受けている。
プロンプトは表示されないが、サーバ側をコマンドで操作出来ている事がわかる。
…まぁ、普通にバックドアですよね、これ。

20151116_000007

 

とりあえず、以上8個を紹介させてもらった。
実際にはまだまだ面白い使い方はあるだろうし、見つけたらまた追記していくことにする。

ネットワークエンジニアの教科書 ネットワークエンジニアの教科書

数字を人の読みやすいように加工する『numfmt』コマンド

$
0
0

シェルスクリプトやCUIでLinuxを操作していると、バイトで記述された容量を人が読みやすい状態に加工したい時がある。
それを簡単に行えるのが、Coreutils 8.22から追加された『numfmt』コマンドだ。

少なくとも、CentOS 7やUbuntu 14.04 LTSでは標準で利用することが出来る。

このコマンドの使い方については、もう見てもらった方が早いだろう。
以下のようにechoで「4096000(4MB相当)」を出力し、それをnumfmtに渡す。すると…

echo 4096000 | numfmt --to=iec

20151118_000013

[root@test-apache ~]# echo 4096000
4096000
[root@test-apache ~]# echo 4096000 | numfmt --to=iec
4.0M

 

このように、人が見てわかりやすい容量に加工してくれるのだ。
区切り文字や何列目の数字を加工するかについても指定できて、地味にかなり便利なコマンド。

もちろん、計算方法も1000で単位を上げるのか、1024で単位を上げるのか「–to=UNIT」で指定可能だ。
以下、指定できるUNITについて、helpの内容を一部抜粋する。

UNIT options:
  none       no auto-scaling is done; suffixes will trigger an error
  auto       accept optional single/two letter suffix:
               1K = 1000,
               1Ki = 1024,
               1M = 1000000,
               1Mi = 1048576,
  si         accept optional single letter suffix:
               1K = 1000,
               1M = 1000000,
               ...
  iec        accept optional single letter suffix:
               1K = 1024,
               1M = 1048576,
               ...
  iec-i      accept optional two-letter suffix:
               1Ki = 1024,
               1Mi = 1048576,
               ...

基本的には、バイト数を計算させるならば「iec」「iec-i」を使えばいいだろう。

その他、こんな事もできる。
例えば、以前こちらで紹介したLinuxの特定ディレクトリ配下で容量を食ってるファイルTOP10を抽出するコマンドと組み合わせると…

ls -la $(find /調べたいディレクトリ -type f) | sort -nr -k5 | head -10 #既存のコマンド
ls -la $(find /調べたいディレクトリ -type f) | sort -nr -k5 | head -10 | numfmt --to=iec --field=5 # numfmtで加工する

20151118_000014

[root@test-centos7 ~]# ls -la $(find /work -type f) | sort -nr -k5 | head -10
-rw-r--r--. 1 root   root   1024000000  7月 26 11:29 /work/test2.bk
-rw-r--r--. 1 root   root   1024000000  7月 26 11:29 /work/test1.bk
-rw-r--r--. 1 root   root   1024000000  7月 11 05:13 /work/test2
-rw-r--r--. 1 root   root   1024000000  7月 11 05:12 /work/test1
-rw-r--r--. 1 root   root    209715200  7月 26 11:28 /work/sample.bk
-rw-r--r--. 1 root   root    209715200  6月  8 23:12 /work/sample
-rw-r--r--. 1 root   root     36814848  7月 26 11:28 /work/test.image.bk
-rw-r--r--. 1 root   root     36814848  6月 20 19:37 /work/test.image
-rw-r--r--. 1 root   root        99973 11月 16 11:44 /work/20151113_134734_AWSテスト.log
-rw-r--r--. 1 root   root        64368 10月 27 06:44 /work/test7_2.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# ls -la $(find /work -type f) | sort -nr -k5 | head -10 | numfmt --to=iec --field=5
-rw-r--r--. 1 root   root         977M  7月 26 11:29 /work/test2.bk
-rw-r--r--. 1 root   root         977M  7月 26 11:29 /work/test1.bk
-rw-r--r--. 1 root   root         977M  7月 11 05:13 /work/test2
-rw-r--r--. 1 root   root         977M  7月 11 05:12 /work/test1
-rw-r--r--. 1 root   root         200M  7月 26 11:28 /work/sample.bk
-rw-r--r--. 1 root   root         200M  6月  8 23:12 /work/sample
-rw-r--r--. 1 root   root          36M  7月 26 11:28 /work/test.image.bk
-rw-r--r--. 1 root   root          36M  6月 20 19:37 /work/test.image
-rw-r--r--. 1 root   root          98K 11月 16 11:44 /work/20151113_134734_AWSテスト.log
-rw-r--r--. 1 root   root          63K 10月 27 06:44 /work/test7_2.sh

 

このように、一度容量順でソートした後でも人の見やすい形式に直す事が出来る。
上の例では空白区切り(デフォルト)の5列目を指定しているが、区切り文字も「–delimiter」オプションで指定可能だ。

細かいオプションや使い方については、また後日まとめてみるかもだが、これは非常に便利なコマンドだ。

 

※追記

うまいこと魅力を伝えられていないようなので追記。
上の例だと分かりにくいが、lsコマンド単体では配下のディレクトリを再帰的にフルパスで一覧取得出来ない。このため、「-S(サイズ順でソート)」では配下のディレクトリにある大きいファイルが見つけられない。
そのためfindと組み合わせ、sortを用いてるのだが、lsで「-h」すると容量は数字として扱えなくなるので、正常にソートされない。

となると、ソート後にファイル容量を変換する必要が出てくる。
そんな時に使えるよ、という例だったのだが、ちょっとわかりにくかったかも知れない。。。

 

CentOS7システム管理ガイドsystemd/NetworkManager/Firewalld徹底攻略 CentOS7システム管理ガイドsystemd/NetworkManager/Firewalld徹底攻略

linuxで指定したファイルの合計サイズを取得する

$
0
0

linuxで、ディレクトリ内のファイルの合計容量を取得するのではなく、個別に指定したファイル(ワイルドカードで拡張子等を指定したファイルなど)の合計サイズを取得する場合、大まかに分けて2つの方法がある。

1.ls(find)とawkで容量の合計を計算する

ls(+find)とawkで、指定したファイルの合計容量を取得することができる。
lsの実行結果を、awkコマンドで加工する事で合計容量の取得を行えば良い。計算対象をうまく記述出来なければ、ファイルにPATHを記述して$(cat ファイル)で読み出せば良い。

もしCentOS7もしくはUbuntu 14.04以降のOSで、かつ人の読みやすい出力形式にしたいならば、「numfmt」コマンドで加工してあげると良いだろう。

ls -la ファイルPATH等条件 | awk '{ total += $5 }; END { print total }'

20151118_000012

[root@test-centos7 ~]# ls -la /work/test*.py
-rw-r--r--. 1 root root 2223 10月 27 07:10 /work/test.py
-rw-r--r--. 1 root root  457 10月 28 20:09 /work/test1.py
-rw-r--r--. 1 root root 3261 10月 28 22:27 /work/test10.py
-rw-r--r--. 1 root root 1567 10月 28 22:26 /work/test11.py
-rwxr-xr-x. 1 root root 4450 11月  3 07:36 /work/test12.py
-rw-r--r--. 1 root root  682 10月 31 11:09 /work/test13.py
-rw-r--r--. 1 root root  505 11月  6 07:02 /work/test14.py
-rw-r--r--. 1 root root  347 11月  5 06:59 /work/test15.py
-rw-r--r--. 1 root root  232 11月  5 07:04 /work/test16.py
-rw-r--r--. 1 root root 1983 11月  6 08:10 /work/test17.py
-rw-r--r--. 1 root root  649 11月  6 15:37 /work/test18.py
-rw-r--r--. 1 root root  904 11月 11 07:15 /work/test19.py
-rw-r--r--. 1 root root 1345 10月 27 07:06 /work/test2.py
-rw-r--r--. 1 root root 1040 11月 12 13:01 /work/test20.py
-rw-r--r--. 1 root root 1028 11月 12 13:03 /work/test21.py
-rw-r--r--. 1 root root   65 11月 12 17:36 /work/test22.py
-rw-r--r--. 1 root root 1254 11月 12 17:49 /work/test23.py
-rw-r--r--. 1 root root 3310 10月 28 20:10 /work/test3.py
-rw-r--r--. 1 root root 7878 10月 28 20:21 /work/test4.py
-rw-r--r--. 1 root root 1299 10月 28 20:22 /work/test5.py
-rw-r--r--. 1 root root 8432 10月 28 20:54 /work/test6.py
-rw-r--r--. 1 root root  313 10月 28 22:20 /work/test7.py
-rw-r--r--. 1 root root 2887 10月 28 22:22 /work/test8.py
-rw-r--r--. 1 root root 4991 10月 28 22:23 /work/test9.py
[root@test-centos7 ~]# ls -la /work/test*.py | awk '{ total += $5 }; END { print total }'
51102
[root@test-centos7 ~]# ls -la /work/test*.py | awk '{ total += $5 }; END { print total }' | numfmt --to=iec
50K

2.du(or 「wc -c」)で取得する

その他、duもしくは「wc -c」で合計容量を取得する方法もある。
こちらは、合計のみを取得したい場合はtailと組み合わせる必要があるが、「-bh」を付与することで人が読みやすい形式に出力することができる。
(「wc -c」の場合は単位がバイトなので、numfmtで読みやすいよう加工する等が必要になる)

du -bhc ファイルPATH等条件 | tail -n 1

20151118_000015

[root@test-centos7 ~]# du -bhc /work/test*.py
2.2K    /work/test.py
457     /work/test1.py
3.2K    /work/test10.py
1.6K    /work/test11.py
4.4K    /work/test12.py
682     /work/test13.py
505     /work/test14.py
347     /work/test15.py
232     /work/test16.py
2.0K    /work/test17.py
649     /work/test18.py
904     /work/test19.py
1.4K    /work/test2.py
1.1K    /work/test20.py
1.1K    /work/test21.py
65      /work/test22.py
1.3K    /work/test23.py
3.3K    /work/test3.py
7.7K    /work/test4.py
1.3K    /work/test5.py
8.3K    /work/test6.py
313     /work/test7.py
2.9K    /work/test8.py
4.9K    /work/test9.py
50K     合計
[root@test-centos7 ~]# du -bhc /work/test*.py | tail -n 1
50K     合計

 

以上、2つの手法について紹介させてもらった。
ファイルをアーカイブ化する前に、元ファイルがどの程度の容量だったのかみるときなどに有効だろう。

 

Linux完全マスターバイブル (100%ムックシリーズ) Linux完全マスターバイブル (100%ムックシリーズ)

ヌルコマンドでシェルスクリプトの変数が空の場合に特定の値を代入させる

$
0
0

シェルスクリプトを書いていると、特定の変数の値が空(NULL)の時はデフォルト値を代入する処理を行う必要が出てくる事がある。
そんなときは、ヌルコマンドで変数が空の時はデフォルト値を代入するように記述すると良いだろう。

変数の値が空の時にデフォルト値を代入する場合は、以下のように記述する。

: ${変数:=デフォルト値}

 

以下の例では、引数を代入する変数『TEST_VAR』に値がない場合、デフォルト値として『DEFAULT_123』という値を代入する

#!/bin/sh
TEST_VAR=$1
: ${TEST_VAR:='DEFAULT_123'}

echo $TEST_VAR

20151117_000000

[root@test-centos7 ~]# cat /work/TEST1.sh
#!/bin/sh
TEST_VAR=$1
: ${TEST_VAR:='DEFAULT_123'}

echo $TEST_VAR
[root@test-centos7 ~]# sh /work/TEST1.sh 123
123
[root@test-centos7 ~]# sh /work/TEST1.sh
DEFAULT_123

 

その他、ヌルコマンドでは以下のような使い方が出来るようだ。

●一時的な代入(変数に対し値の代入までは行わない)

変数が空(NULL)は一時的な代入を行い、その後の変数にまで影響しない場合は、「${変数:-代入値}」と記述する。
例として、以下のようなスクリプトを実行する。

#!/bin/sh
TEST_VAR=$1

echo "#変数が空の時"
echo ${TEST_VAR:-'DEFAULT_123'}
echo ""

echo "#再度呼び出す"
echo $TEST_VAR
echo ""

20151117_000001

[root@test-centos7 ~]# cat /work/TEST2.sh
#!/bin/sh
TEST_VAR=$1

echo "#変数が空の時"
echo ${TEST_VAR:-'DEFAULT_123'}
echo ""

echo "#再度呼び出す"
echo $TEST_VAR
echo ""
[root@test-centos7 ~]#
[root@test-centos7 ~]# sh /work/TEST2.sh
#変数が空の時
DEFAULT_123

#再度呼び出す


[root@test-centos7 ~]#
[root@test-centos7 ~]# sh /work/TEST2.sh 1
#変数が空の時
1

#再度呼び出す
1

 

●変数が空(NULL)の場合はNULLを、値が入っている場合は別の値を返す

変数が空(NULL)の場合にはそのままNULLを、値が代入されている場合のみ別の値を代入することもできる。
その場合は、「${変数:+代入値}」と記述すればよい。なお、この時変数に値は代入されないので注意。

以下、例となるスクリプトとその実行結果を記述しておく。

#!/bin/sh
TEST_VAR=$1

echo "#変数が空ではない時"
echo ${TEST_VAR:+'DEFAULT_123'}
echo ""

echo "#再度呼び出す"
echo $TEST_VAR
echo ""

20151117_000002

[root@test-centos7 ~]# cat /work/TEST3.sh
#!/bin/sh
TEST_VAR=$1

echo "#変数が空ではない時"
echo ${TEST_VAR:+'DEFAULT_123'}
echo ""

echo "#再度呼び出す"
echo $TEST_VAR
echo ""
[root@test-centos7 ~]#
[root@test-centos7 ~]# sh /work/TEST3.sh 123
#変数が空ではない時
DEFAULT_123

#再度呼び出す
123

[root@test-centos7 ~]#
[root@test-centos7 ~]# sh /work/TEST3.sh
#変数が空ではない時


#再度呼び出す

 

●変数が空(NULL)の場合はエラー終了する

変数が空の場合、その箇所でスクリプトをエラー終了させることも出来る。
その場合は、「${変数:?エラーメッセージ}」というように記述する。

以下、スクリプト例。

#!/bin/sh
TEST_VAR=$1
: ${TEST_VAR:?"変数がNULLです"}

echo $TEST_VAR

20151117_000003

[root@test-centos7 ~]# cat /work/TEST4.sh
#!/bin/sh
TEST_VAR=$1
: ${TEST_VAR:?"変数がNULLです"}

echo $TEST_VAR
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 変数がNULLの場合
[root@test-centos7 ~]# sh /work/TEST4.sh
/work/TEST4.sh: 行 3: TEST_VAR: 変数がNULLです
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 変数がNULLではない場合
[root@test-centos7 ~]# sh /work/TEST4.sh 12345
12345

 

うまく使いこなせれば、スクリプトの記述量も少なくできそうだ。

UNIXシェルスクリプト マスターピース132 UNIXシェルスクリプト マスターピース132

Linuxのzip/unzipコマンドで覚えておきたい使い方11個

$
0
0

Linuxでzipファイルを扱う際、欠かせないのがzip/unzipコマンド。
今回は、このコマンドについて覚えておきたい使い方について紹介しておく。

1.基本的な使い方

基本的には、zipファイルとして圧縮もしくは解凍する際は以下のようにコマンドを実行する。

zip 作成するZIPファイルPATH 圧縮対象PATH ... # 圧縮時
unzip 解凍するZIPファイルPATH # 解凍時

20151117_000004

[root@test-centos7 ~]# zip /tmp/test1.zip /work3/TEST1.sh /work3/TEST2.sh
  adding: work3/TEST1.sh (deflated 16%)
  adding: work3/TEST2.sh (deflated 27%)
[root@test-centos7 ~]#
[root@test-centos7 ~]# unzip /tmp/test1.zip
Archive:  /tmp/test1.zip
  inflating: work3/TEST1.sh
  inflating: work3/TEST2.sh

 

なお、作成するファイルPATHに既存のzipファイルを指定すると、ファイルのUPDATE及び追加をデフォルトで行ってくれる。
(削除はしない)

20151117_000006

[root@test-centos7 ~]# zip /tmp/test1.zip /work3/TEST1.sh /work3/TEST2.sh
  adding: work3/TEST1.sh (deflated 16%)
  adding: work3/TEST2.sh (deflated 27%)
[root@test-centos7 ~]# ls -la /tmp/test1.zip
-rw-r--r--. 1 root root 493 11月 17 06:24 /tmp/test1.zip
[root@test-centos7 ~]# zip /tmp/test1.zip /work3/TEST1.sh /work3/TEST2.sh /work3/TEST3.sh
updating: work3/TEST1.sh (deflated 16%)
updating: work3/TEST2.sh (deflated 27%)
  adding: work3/TEST3.sh (deflated 25%)
[root@test-centos7 ~]# ls -la /tmp/test1.zip
-rw-r--r--. 1 root root 762 11月 17 06:24 /tmp/test1.zip

 

2.ディレクトリを指定して再帰的に圧縮する

オプション無しの場合、zipコマンドではディレクトリのみを指定すると中のファイルは圧縮してくれない。
ディレクトリ配下を再帰的に圧縮する場合は、「-r」オプションを付与する。

zip -r 作成するzipファイルPATH 再帰的に圧縮するフォルダ

20151117_000005

[root@test-centos7 ~]# zip -r /tmp/test1.zip /work3/
updating: work3/TEST1.sh (deflated 16%)
updating: work3/TEST2.sh (deflated 27%)
  adding: work3/ (stored 0%)
  adding: work3/work/ (stored 0%)
  adding: work3/work/ln_test.txt (deflated 46%)
  adding: work3/work/ln_test.txt2 (deflated 46%)
  adding: work3/work/aaaaa.txt (stored 0%)
  adding: work3/work/bbbbb.txt (stored 0%)
  adding: work3/work/ccccc.txt (stored 0%)
  adding: work3/work/ddddd.txt (stored 0%)
  adding: work3/work/test.txt (deflated 46%)
  adding: work3/work/test2.txt (deflated 69%)
  adding: work3/aaaaa.txt (stored 0%)
  adding: work3/bbbbb.txt (stored 0%)
  adding: work3/ccccc.txt (stored 0%)
  adding: work3/ln_aaaaa.txt (stored 0%)
  ...

 

3.圧縮対象となるファイル名を指定して圧縮する

特定の拡張子のファイルのみを圧縮する場合は、「-i」オプションをコマンドの末尾に付与する。
なお、指定できるファイル名はpathである点に注意。ファイル名だけで圧縮が出来ないので、基本的にはワイルドカードと組み合わせて使用する。

zip 作成するZIPファイルPATH 圧縮対象PATH ... -i 圧縮対象ファイル名

20151117_000007

[root@test-centos7 ~]# zip -r /tmp/test1.zip /work3/ -i *test*.py
  adding: work3/test.py (deflated 65%)
  adding: work3/test1.py (deflated 51%)
  adding: work3/test10.py (deflated 73%)
  adding: work3/test11.py (deflated 59%)
  adding: work3/test12.py (deflated 71%)
  adding: work3/test13.py (deflated 60%)
  adding: work3/test14.py (deflated 45%)
  adding: work3/test15.py (deflated 35%)
  ...

 

4.zipファイルの解凍先を指定する

unzipで解凍先のPATHを指定する場合は、「-d」オプションで解凍先PATHを指定することで行える。

unzip 解凍するZIPファイルPATH -d 解凍先PATH

20151117_000008

[root@test-centos7 ~]# mkdir /tmp/test1233
[root@test-centos7 ~]# unzip /tmp/test1.zip -d /tmp/test1233
Archive:  /tmp/test1.zip
  inflating: /tmp/test1233/work3/test.py
  inflating: /tmp/test1233/work3/test1.py
  inflating: /tmp/test1233/work3/test10.py
  inflating: /tmp/test1233/work3/test11.py
  inflating: /tmp/test1233/work3/test12.py
  inflating: /tmp/test1233/work3/test13.py
  inflating: /tmp/test1233/work3/test14.py
  inflating: /tmp/test1233/work3/test15.py
  ...

 

5.パスワードを指定して圧縮する

zipコマンドでは、「-e」オプションを付与することで圧縮ファイルにパスワードを付与することも出来る。

zip -e 作成するZIPファイルPATH 圧縮対象PATH ...

20151118_000000

[root@test-centos7 ~]# zip -er /tmp/test1.zip /work3/ -i *test1*.py
Enter password:
Verify password:
  adding: work3/test1.py (deflated 51%)
  adding: work3/test10.py (deflated 73%)
  adding: work3/test11.py (deflated 59%)
  adding: work3/test12.py (deflated 71%)
  adding: work3/test13.py (deflated 60%)
  adding: work3/test14.py (deflated 45%)
  adding: work3/test15.py (deflated 35%)
  adding: work3/test16.py (deflated 29%)
  adding: work3/test17.py (deflated 66%)
  adding: work3/test18.py (deflated 43%)
  adding: work3/test19.py (deflated 57%)
[root@test-centos7 ~]#
[root@test-centos7 ~]# unzip /tmp/test1.zip
Archive:  /tmp/test1.zip
[/tmp/test1.zip] work3/test1.py password:
  inflating: work3/test1.py
  inflating: work3/test10.py
  inflating: work3/test11.py
  inflating: work3/test12.py
  inflating: work3/test13.py
  inflating: work3/test14.py
  inflating: work3/test15.py
  inflating: work3/test16.py
  inflating: work3/test17.py
  inflating: work3/test18.py
  inflating: work3/test19.py

6.zipファイルの中身を確認する

zipファイルの中身を確認する場合は、unzipコマンドで「-l」オプションを使用すると良いだろう。

unzip -l 対象となるzipファイルのPATH

20151118_000001

[root@test-centos7 ~]# unzip -l /tmp/test1.zip
Archive:  /tmp/test1.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      457  11-17-2015 06:02   work3/test1.py
     3261  11-17-2015 06:02   work3/test10.py
     1567  11-17-2015 06:02   work3/test11.py
     4450  11-17-2015 06:02   work3/test12.py
      682  11-17-2015 06:02   work3/test13.py
      505  11-17-2015 06:02   work3/test14.py
      347  11-17-2015 06:02   work3/test15.py
      232  11-17-2015 06:02   work3/test16.py
     1983  11-17-2015 06:02   work3/test17.py
      649  11-17-2015 06:02   work3/test18.py
      904  11-17-2015 06:02   work3/test19.py
---------                     -------
    15037                     11 files

 

7.既存のzipファイルにファイルを追加・更新する

既存のzipファイルに対して、ファイルを追加する場合はオプション無しで追加・更新が可能である。

20151118_000003

[root@test-centos7 ~]# zip -r /tmp/test1.zip /work3/ -i *test1?.py
  adding: work3/test10.py (deflated 73%)
  adding: work3/test11.py (deflated 59%)
  adding: work3/test12.py (deflated 71%)
  adding: work3/test13.py (deflated 60%)
  adding: work3/test14.py (deflated 45%)
  adding: work3/test15.py (deflated 35%)
  adding: work3/test16.py (deflated 29%)
  adding: work3/test17.py (deflated 66%)
  adding: work3/test18.py (deflated 43%)
  adding: work3/test19.py (deflated 57%)
[root@test-centos7 ~]# zip -r /tmp/test1.zip /work3/ -i *test1*.py
updating: work3/test10.py (deflated 73%)
updating: work3/test11.py (deflated 59%)
updating: work3/test12.py (deflated 71%)
updating: work3/test13.py (deflated 60%)
updating: work3/test14.py (deflated 45%)
updating: work3/test15.py (deflated 35%)
updating: work3/test16.py (deflated 29%)
updating: work3/test17.py (deflated 66%)
updating: work3/test18.py (deflated 43%)
updating: work3/test19.py (deflated 57%)
  adding: work3/test1.py (deflated 51%)

 

変動のあったファイルのみを置き換えるする(新規追加もしない)場合は、「-f」オプションを、変動のあったファイルおよび新規のファイルのみを追加する場合は「-u」オプションを付与する。

zip -f 対象となるZIPファイルPATH 圧縮対象PATH ... # 変動のあったファイルのみ置き換える(新規ファイルは追加しない)
zip -u 対象となるZIPファイルPATH 圧縮対象PATH ... # 変動のあったファイルおよび新規ファイルを更新・追加する

20151118_000005

[root@test-centos7 ~]# zip -r /tmp/test1.zip /work3/ -i *test1*.py
  adding: work3/test1.py (deflated 51%)
  adding: work3/test10.py (deflated 73%)
  adding: work3/test11.py (deflated 59%)
  adding: work3/test12.py (deflated 71%)
  adding: work3/test13.py (deflated 60%)
  adding: work3/test14.py (deflated 45%)
  adding: work3/test15.py (deflated 35%)
  adding: work3/test16.py (deflated 30%)
  adding: work3/test17.py (deflated 66%)
  adding: work3/test18.py (deflated 43%)
  adding: work3/test19.py (deflated 57%)
[root@test-centos7 ~]#
[root@test-centos7 ~]# echo "aaaaa" >> /work3/test12.py
[root@test-centos7 ~]# zip -fr /tmp/test1.zip /work3/ -i *test*.py
freshening: work3/test12.py (deflated 71%)
[root@test-centos7 ~]#
[root@test-centos7 ~]# echo "aaaaa" >> /work3/test16.py
[root@test-centos7 ~]# zip -ur /tmp/test1.zip /work3/ -i *test*.py
updating: work3/test16.py (deflated 31%)
  adding: work3/test.py (deflated 65%)
  adding: work3/test2.py (deflated 63%)
  adding: work3/test20.py (deflated 50%)
  adding: work3/test21.py (deflated 70%)
  adding: work3/test22.py (deflated 25%)
  adding: work3/test23.py (deflated 57%)
  adding: work3/test3.py (deflated 69%)
  adding: work3/test4.py (deflated 71%)
  adding: work3/test5.py (deflated 62%)
  adding: work3/test6.py (deflated 72%)
  adding: work3/test7.py (deflated 42%)
  adding: work3/test8.py (deflated 64%)
  adding: work3/test9.py (deflated 84%)

 

8.既存のzipファイルから一部を削除する

既存のzipファイルから中のファイルを一部削除する場合、zipコマンドで「-d」オプションを用いる。

zip -d 対象となるzipファイルのPATH -d 削除対象ファイルのPATH

20151118_000006

[root@test-centos7 ~]# unzip -l /tmp/test1.zip
Archive:  /tmp/test1.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      457  11-17-2015 06:02   work3/test1.py
     3261  11-17-2015 06:02   work3/test10.py
     1567  11-17-2015 06:02   work3/test11.py
      694  11-18-2015 05:06   work3/test13.py
      347  11-17-2015 06:02   work3/test15.py
      244  11-18-2015 05:08   work3/test16.py
     1983  11-17-2015 06:02   work3/test17.py
      649  11-17-2015 06:02   work3/test18.py
      904  11-17-2015 06:02   work3/test19.py
---------                     -------
    10106                     9 files
[root@test-centos7 ~]# zip -d /tmp/test1.zip work3/test1{6,7,8}.py
deleting: work3/test16.py
deleting: work3/test17.py
deleting: work3/test18.py
[root@test-centos7 ~]# unzip -l /tmp/test1.zip
Archive:  /tmp/test1.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      457  11-17-2015 06:02   work3/test1.py
     3261  11-17-2015 06:02   work3/test10.py
     1567  11-17-2015 06:02   work3/test11.py
      694  11-18-2015 05:06   work3/test13.py
      347  11-17-2015 06:02   work3/test15.py
      904  11-17-2015 06:02   work3/test19.py
---------                     -------
     7230                     6 files

 

9.指定したファイル・ディレクトリのみを解凍する

zipファイルの中から、意図したファイルやディレクトリのみを解凍する場合は、unzipコマンドで引数としてファイルPATHを指定してあげればいい。
なお、ディレクトリの場合は再帰的に解凍出来ないので、ワイルドカード付きで指定する必要がある。

unzip 対象となるzipファイルのPATH 解凍するファイル・ディレクトリPATH

20151118_000008

[root@test-centos7 ~]# unzip -l /tmp/test1.zip
Archive:  /tmp/test1.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      457  11-17-2015 06:02   work3/test1.py
     3261  11-17-2015 06:02   work3/test10.py
     1567  11-17-2015 06:02   work3/test11.py
      694  11-18-2015 05:06   work3/test13.py
      347  11-17-2015 06:02   work3/test15.py
      904  11-17-2015 06:02   work3/test19.py
       67  11-17-2015 05:01   work/TEST1.sh
      141  11-17-2015 05:04   work/TEST2.sh
      150  11-17-2015 05:14   work/TEST3.sh
       75  11-17-2015 05:18   work/TEST4.sh
       67  11-17-2015 05:17   work/TESTr.sh
---------                     -------
     7730                     11 files
[root@test-centos7 ~]# unzip /tmp/test1.zip work3/test10.py
Archive:  /tmp/test1.zip
  inflating: work3/test10.py
[root@test-centos7 ~]# unzip /tmp/test1.zip work/*
Archive:  /tmp/test1.zip
  inflating: work/TEST1.sh
  inflating: work/TEST2.sh
  inflating: work/TEST3.sh
  inflating: work/TEST4.sh
  inflating: work/TESTr.sh

 

10.高圧縮率 or 高速圧縮にする

zipコマンドでは、(そんなに変わらないけど)オプションによって圧縮率を変動させることが出来る。

  • -0 … 無圧縮(ただまとめただけ)
  • -1 … 圧縮率は低いが高速
  • -9 … 圧縮率は高いが低速

20151118_000009

[root@test-centos7 ~]# ls -ls /work3/test1*.py | awk '{sum = sum + $6} END {print sum}'
15067
[root@test-centos7 ~]# zip -0 /tmp/test-0.zip /work/test1*.py
  adding: work/test1.py (stored 0%)
  adding: work/test10.py (stored 0%)
  adding: work/test11.py (stored 0%)
  adding: work/test12.py (stored 0%)
  adding: work/test13.py (stored 0%)
  adding: work/test14.py (stored 0%)
  adding: work/test15.py (stored 0%)
  adding: work/test16.py (stored 0%)
  adding: work/test17.py (stored 0%)
  adding: work/test18.py (stored 0%)
  adding: work/test19.py (stored 0%)
[root@test-centos7 ~]# zip -1 /tmp/test-1.zip /work/test1*.py
  adding: work/test1.py (deflated 51%)
  adding: work/test10.py (deflated 69%)
  adding: work/test11.py (deflated 57%)
  adding: work/test12.py (deflated 68%)
  adding: work/test13.py (deflated 57%)
  adding: work/test14.py (deflated 44%)
  adding: work/test15.py (deflated 35%)
  adding: work/test16.py (deflated 28%)
  adding: work/test17.py (deflated 64%)
  adding: work/test18.py (deflated 43%)
  adding: work/test19.py (deflated 55%)
[root@test-centos7 ~]# zip -9 /tmp/test-9.zip /work/test1*.py
  adding: work/test1.py (deflated 51%)
  adding: work/test10.py (deflated 73%)
  adding: work/test11.py (deflated 59%)
  adding: work/test12.py (deflated 71%)
  adding: work/test13.py (deflated 60%)
  adding: work/test14.py (deflated 45%)
  adding: work/test15.py (deflated 35%)
  adding: work/test16.py (deflated 29%)
  adding: work/test17.py (deflated 66%)
  adding: work/test18.py (deflated 43%)
  adding: work/test19.py (deflated 57%)
[root@test-centos7 ~]# ls -la /tmp/test-*
-rw-r--r--. 1 root root 16773 11月 18 05:49 /tmp/test-0.zip
-rw-r--r--. 1 root root  7547 11月 18 05:49 /tmp/test-1.zip
-rw-r--r--. 1 root root  7117 11月 18 05:49 /tmp/test-9.zip

 

上の例を見るとわかるように、それぞれのオプションによってzipファイルの容量が異なっている。
無圧縮においてはむしろ容量が増えているような状態だ。

基本的には、時間を掛けたくない場合は「-1」を、そんなに圧縮率は変わらないが、ある程度容量を抑えたい場合は「-9」を付与すればよいだろう。

 

11.zipファイルの解凍テストを行う

ファイルの解凍を実際に行わず、動作テストのみを行う場合はunzipコマンドで「-t」オプションを付与する。

unzip -t 対象となるzipファイルのPATH

20151118_000010

[root@test-centos7 ~]# unzip -t /tmp/test1.zip
Archive:  /tmp/test1.zip
    testing: work3/test1.py           OK
    testing: work3/test10.py          OK
    testing: work3/test11.py          OK
    testing: work3/test13.py          OK
    testing: work3/test15.py          OK
    testing: work3/test19.py          OK
    testing: work/TEST1.sh            OK
    testing: work/TEST2.sh            OK
    testing: work/TEST3.sh            OK
    testing: work/TEST4.sh            OK
    testing: work/TESTr.sh            OK
No errors detected in compressed data of /tmp/test1.zip.
[root@test-centos7 ~]# ls -la work{,3}/
ls: work/ にアクセスできません: そのようなファイルやディレクトリはありません
ls: work3/ にアクセスできません: そのようなファイルやディレクトリはありません

 

詳解 圧縮処理プログラミング C言語で実装する圧縮処理アルゴリズム 詳解 圧縮処理プログラミング C言語で実装する圧縮処理アルゴリズム

シェルでグルーピングを利用してリダイレクトを一発で行う

$
0
0

リダイレクトで、複数のコマンドの実行結果を同じファイルに書き出したいとき、1コマンドに対し1リダイレクトの処理を書くと結構面倒くさい。
そんなときは、グルーピング({}で実行するコマンドを囲む)してリダイレクトを行うと良いだろう。

20151116_000015

 

[root@test-centos7 ~]# { echo "aaaaaa";
> echo "bbbbb";
> echo "ccccc"; } > /tmp/test1234.txt
[root@test-centos7 ~]#
[root@test-centos7 ~]# cat /tmp/test1234.txt
aaaaaa
bbbbb
ccccc

コンソールから実行する場合は「;(セミコロン)」が各コマンドの末尾に必要になるが、これはシェルスクリプトで書く場合は不要。

UNIXシェルスクリプト マスターピース132 UNIXシェルスクリプト マスターピース132

nc(Ncat)コマンドで覚えておきたい使い方3個(ncコマンドCentOS 7版)

$
0
0

前回も紹介したLinuxでポートの疎通確認を行う際によく用いるncコマンド。
実はこのコマンド、netcatではなくCentOS 7の場合だとnampプロジェクトのncatに置き換えられているのだ。

今後はncもこのncatコマンドに置き換えられている事になるので、このコマンドの使い方についても(あんま変わらんけど)紹介することにした。
なお、検証に使用したコマンドはCentOS 7に入れている”Ncat: Version 6.40 ( http://nmap.org/ncat )”とする。

20151116_000000

[root@test-centos7 ~]# nc --version
Ncat: Version 6.40 ( http://nmap.org/ncat )

 

コマンドが置き換わったため、netcatでは使えていたオプションが無かったりする。
例えば「-z」オプションなんて無いので、レンジ指定で空きポートを確認する手法は使うことが出来ないので注意が必要だ。

なお、前回紹介した手法のうち、以下についてはnetcatコマンドと変わらないため、割愛する。
変わった(できなくなった)のは、ポート範囲を指定してのスキャンだけだ。

  • 1.基本的な使い方・クライアントとして動作させる
  • 2.基本的な使い方・サーバとして動作させる
  • 3.ファイルを転送する
  • 4.IPv4、IPv6を指定する
  • 5.通信の詳細を取得する
  • 6.ソースアドレス・ポートを指定する
  • 8.ポートへのアクセス時にコマンド(bash等)が実行されるようにする

 

1.通信にsslを利用する

ncatの場合、「–ssl」を付与することで通信にSSLを使用することができる。
デフォルトではSHA1で通信が行われる。

nc -vl ポート番号 --ssl # サーバ側
nc -v 対象ホスト(IPアドレス等) ポート番号 --ssl

20151116_000010

SSLで通信を行わせる場合は、サーバ・クライアントともに「–ssl」オプションを付与する必要がある点に注意。
SSLを利用できるということで、その他のオプション(鍵ファイルを指定したり等)も付与する事が出来る。

2.SCTPで通信を行う

あまり使うシチュエーションは思いつかないが、「–sctp」を付与することで、SCTPプロトコルでの通信を行う事も出来る。

20151116_000012

 

3.送信・受信専用にする

オプションとして「–send-only」を付与することで送信専用に、「–recv-only」を付与することで受信専用として動作させることができる。
例えば、右側のコンソールをクライアントとして送信専用にすると、左のコンソールで入力した内容は受信されない。

20151116_000014

 

その他、細かいオプション(同時接続数の制限や接続許可ホストの指定、コマンドの実行方法など)もあるが基本的にはnetcatとそう変わらない。

CentOS7システム管理ガイドsystemd/NetworkManager/Firewalld徹底攻略 CentOS7システム管理ガイドsystemd/NetworkManager/Firewalld徹底攻略

シェルスクリプトで『getopts』を使ってオプションの処理を行わせる

$
0
0

仕事などでシェルスクリプトを作っていると、引数としてオプションを付与させるようなスクリプトを作りたくなる事がある。
そういったオプション関係の処理を簡単に行えるのが、今回紹介する『getopts』コマンドだ。仕事でスクリプトを組んでいれば、一度は利用するだろう。

このコマンドを利用することで、オプションを付与させるタイプのシェルスクリプトを簡単に作成することが可能になる。
基本的には、以下の例のようにwhile、caseと組み合わせる使い方がセオリーだ。

●example.sh

#!/bin/sh

############################################
# この例では、以下のオプションを付与させる #
# -a … オプション                         #
# -b … 文字列を後に付与するオプション     #
# -c … オプション                         #
############################################

# FLAG_A … 「-a」オプションが認識されているかどうか
# ARGS_B … 「-b」オプションで付与した文字列を格納
# FLAG_C … 「-c」オプションが認識されているかどうか
FLAG_A=0
ARGS_B=""
FLAG_C=0

# whileでgetoptsを用いる
# getoptsに引数として、使用するオプションの文字列を渡している。
# 文字列を後に付与するオプションの場合、「文字:」といった書き方をする。
while getopts "ab:c" op
do
    case $op in
        a)
          FLAG_A=1
          ;;
        b)
          # オプションに対する引数は「$OPTARG」で取得できる
          ARGS_B="$OPTARG"
          ;;
        c)
          FLAG_C=1
          ;;
        *)
          exit 1
          ;;
    esac
done

echo "指定されたオプションであれば「1」もしくは付与した文字列が表示される"
echo "-a: " $FLAG_A
echo "-b: " ${ARGS_B:="指定されませんでした"}
echo "-c: " $FLAG_C

それでは、実際に上のスクリプトを実行してみよう。

20151118_000017

[root@test-centos7 ~]# sh /work/example.sh
指定されたオプションであれば「1」もしくは付与した文字列が表示される
-a:  0
-b:  オプションが付与されませんでした
-c:  0
[root@test-centos7 ~]#
[root@test-centos7 ~]# sh /work/example.sh -b 'aaaaa' -c
指定されたオプションであれば「1」もしくは付与した文字列が表示される
-a:  0
-b:  aaaaa
-c:  1
[root@test-centos7 ~]#
[root@test-centos7 ~]# sh /work/example.sh -b -c
指定されたオプションであれば「1」もしくは付与した文字列が表示される
-a:  0
-b:  -c
-c:  0
[root@test-centos7 ~]#
[root@test-centos7 ~]# sh /work/example.sh -b
/work/example.sh: オプションには引数が必要です -- b
[root@test-centos7 ~]#
[root@test-centos7 ~]# sh /work/example.sh -d
/work/example.sh: 不正なオプションです -- d

順番通りにオプションを書かなくても正常に認識されるし、不正なオプションの場合はその旨を表示してくれている。

UNIXシェルスクリプト マスターピース132 UNIXシェルスクリプト マスターピース132

tarコマンド(GNU拡張版)で覚えておきたい使い方13個

$
0
0

Linux、UNIXでアーカイブファイルに関するコマンドといえば、やはりtarコマンドだろう。
アーカイブファイルとは、多数のファイルをそのユーザ・グループ情報やパーミッション、タイムスタンプ等の情報と共に、一つにまとめたファイルのことだ。ただのアーカイブファイルだと圧縮までは行われないため、通常はgzipと組み合わせて圧縮もさせる。

今回はこのtarを作成するtarコマンドについて、覚えておくと便利な使い方を紹介する。
なお、使用したのはCentOS 7にインストールされている以下のバージョンとなる。

20151125_000013

[root@test-centos7 ~]# tar --version
tar (GNU tar) 1.26
Copyright (C) 2011 Free Software Foundation, Inc.
使用許諾 GPLv3+: GNU GPL version 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

[参考訳]
これはフリーソフトウェアです. 変更と再配布は自由です.
法律で認められる範囲で「無保証」です.

作者: John Gilmore, Jay Fenlason.

 

1.アーカイブファイルの作成

アーカイブファイルを作成する場合は、通常だと以下のようにコマンドを実行する。
なお、アーカイブに含める対象としてディレクトリを指定すると再帰的に含めてくれる。

tar cvf 作成するアーカイブファイル アーカイブに含めるファイルPATH ...

 

指定しているオプション「cvf」それぞれの意味は以下。

  • c … アーカイブファイルを作成する
  • v … 詳細の表示
  • f … 作成するアーカイブファイル名を指定

 

gzipによる圧縮も同時に行う場合は、「z」オプションを付与する。
基本的には、こちらで覚えておけば問題ない。

tar czvf 作成するアーカイブファイル アーカイブに含めるファイルPATH ...

 

bz2による圧縮を行う場合は、「j」オプションを付与する。

tar cjvf 作成するアーカイブファイル アーカイブに含めるファイルPATH ...

20151125_000003

[root@test-centos7 ~]# tar cvf /tmp/tar_test.tar /work/test12.*
tar: メンバ名から先頭の `/' を取り除きます
/work/test12.py
/work/test12.py.old
/work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar czvf /tmp/tar_test.tar.gz /work/test12.*
tar: メンバ名から先頭の `/' を取り除きます
/work/test12.py
/work/test12.py.old
/work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar cjvf /tmp/tar_test.tar.bz2 /work/test12.*
tar: メンバ名から先頭の `/' を取り除きます
/work/test12.py
/work/test12.py.old
/work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# ls -la /tmp/tar_test.*
-rw-r--r--. 1 root root 20480 11月 25 08:20 /tmp/tar_test.tar
-rw-r--r--. 1 root root  2107 11月 25 08:21 /tmp/tar_test.tar.bz2
-rw-r--r--. 1 root root  1838 11月 25 08:20 /tmp/tar_test.tar.gz
[root@test-centos7 ~]#
[root@test-centos7 ~]# file /tmp/tar_test.*
/tmp/tar_test.tar:     POSIX tar archive (GNU)
/tmp/tar_test.tar.bz2: bzip2 compressed data, block size = 900k
/tmp/tar_test.tar.gz:  gzip compressed data, from Unix, last modified: Wed Nov 25 08:20:54 2015

 

2.アーカイブファイルの展開

アーカイブファイルを展開する場合は、以下のようにコマンドを実行する。
なお、展開したファイルはカレントディレクトリ配下に展開される。

tar xvf 展開するアーカイブファイルPATH

20151125_000004

[root@test-centos7 ~]# ls -la /tmp/tar_test.*
-rw-r--r--. 1 root root 20480 11月 25 08:20 /tmp/tar_test.tar
-rw-r--r--. 1 root root  2107 11月 25 08:21 /tmp/tar_test.tar.bz2
-rw-r--r--. 1 root root  1838 11月 25 08:20 /tmp/tar_test.tar.gz
[root@test-centos7 ~]#
[root@test-centos7 ~]# file /tmp/tar_test.*
/tmp/tar_test.tar:     POSIX tar archive (GNU)
/tmp/tar_test.tar.bz2: bzip2 compressed data, block size = 900k
/tmp/tar_test.tar.gz:  gzip compressed data, from Unix, last modified: Wed Nov 25 08:20:54 2015
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar xvf /tmp/tar_test.tar
work/test12.py
work/test12.py.old
work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar xvf /tmp/tar_test.tar.gz
work/test12.py
work/test12.py.old
work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar xvf /tmp/tar_test.tar.bz2
work/test12.py
work/test12.py.old
work/test12.sh

 

3.アーカイブファイルの展開先ディレクトリを指定する

アーカイブファイル展開時に、展開先のディレクトリを指定する場合は「-C」オプションにて指定することが出来る。

tar xvf 展開するアーカイブファイルPATH -C 展開先ディレクトリ

20151125_000008

[root@test-centos7 ~]# pwd
/root
[root@test-centos7 ~]# tar xvf /tmp/tar_test.tar.gz -C /work4
work/test12.py
work/test12.py.old
work/test12.sh
[root@test-centos7 ~]# ls -la /work4/
合計 4
drwxr-xr-x.  3 root root   17 11月 25 14:32 .
drwxr-xr-x. 33 root root 4096 11月 25 14:31 ..
drwxr-xr-x.  2 root root   58 11月 25 14:32 work
[root@test-centos7 ~]#
[root@test-centos7 ~]# ls -la $(find /work4/ -type f)
-rwxr-xr-x. 1 root root 4450 11月  3 07:36 /work4/work/test12.py
-rwxr-xr-x. 1 root root 4450 11月  3 07:36 /work4/work/test12.py.old
-rw-r--r--. 1 root root  573 10月 28 20:39 /work4/work/test12.sh

 

4.アーカイブファイルの中身をリスト表示する

アーカイブファイルの中身をリスト表示する場合は、「t」オプションを用いる。

tar tvf 中身を確認するアーカイブファイルPATH
tar tvf 中身を確認するアーカイブファイルPATH アーカイブファイル内の表示させたいファイルPATH # 特定のファイルのみ表示させたい場合

20151125_000007

[root@test-centos7 ~]# ls -la /tmp/tar_test.*
-rw-r--r--. 1 root root 20480 11月 25 08:20 /tmp/tar_test.tar
-rw-r--r--. 1 root root  2107 11月 25 08:21 /tmp/tar_test.tar.bz2
-rw-r--r--. 1 root root  1838 11月 25 08:20 /tmp/tar_test.tar.gz
[root@test-centos7 ~]#
[root@test-centos7 ~]# file /tmp/tar_test.*
/tmp/tar_test.tar:     POSIX tar archive (GNU)
/tmp/tar_test.tar.bz2: bzip2 compressed data, block size = 900k
/tmp/tar_test.tar.gz:  gzip compressed data, from Unix, last modified: Wed Nov 25 08:20:54 2015
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py.old
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py.old
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.bz2
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py.old
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# # 特定のファイルのみを表示する場合(例:test12.pyのみ指定)
[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz work/test12.py
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py

 

5.アーカイブファイルから特定のファイルのみを展開させる

アーカイブファイルから、特定のファイルのみを展開させる場合は、以下のように引数として対象のファイルPATHを指定する。

tar xvf 展開するアーカイブファイルPATH 展開するファイル

20151125_000010

[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py.old
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar xvf /tmp/tar_test.tar.gz work/test12.sh
work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# ls -la work/
合計 8
drwxr-xr-x.  2 root root   22 11月 25 14:37 .
dr-xr-x---. 23 root root 4096 11月 25 14:37 ..
-rw-r--r--.  1 root root  573 10月 28 20:39 test12.sh

6.アーカイブファイルにファイル・ディレクトリを追加する

既存のアーカイブファイルにファイルやディレクトリを追加する場合は、「r」オプションを付与する。

tar rvf 対象のアーカイブファイルPATH 追加するファイル・ディレクトリPATH

20151125_000011

[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py.old
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar rvf /tmp/tar_test.tar.gz /work/test1*.sh
tar: メンバ名から先頭の `/' を取り除きます
/work/test10.sh
/work/test11.sh
/work/test12.sh
/work/test13.sh
/work/test14.sh
/work/test15.sh
/work/test16.sh
/work/test17.sh
/work/test18.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py.old
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root        96 2015-10-14 09:00 work/test10.sh
-rw-r--r-- root/root      1168 2015-10-28 20:24 work/test11.sh
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root      1276 2015-10-28 20:49 work/test13.sh
-rw-r--r-- root/root     64363 2015-10-28 21:04 work/test14.sh
-rw-r--r-- root/root      4871 2015-10-28 21:19 work/test15.sh
-rw-r--r-- root/root       106 2015-10-28 21:48 work/test16.sh
-rw-r--r-- root/root      3570 2015-10-28 22:09 work/test17.sh
-rw-r--r-- root/root        88 2015-11-15 08:56 work/test18.sh

 

7.アーカイブファイルからファイル・ディレクトリを削除する

既存のアーカイブファイルからファイルやディレクトリを削除する場合は、「–delete」オプションを用いる。

tar vf 対象のアーカイブファイルPATH --delete 削除するファイル

20151125_000012

[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py
-rwxr-xr-x root/root      4450 2015-11-03 07:36 work/test12.py.old
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root        96 2015-10-14 09:00 work/test10.sh
-rw-r--r-- root/root      1168 2015-10-28 20:24 work/test11.sh
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root      1276 2015-10-28 20:49 work/test13.sh
-rw-r--r-- root/root     64363 2015-10-28 21:04 work/test14.sh
-rw-r--r-- root/root      4871 2015-10-28 21:19 work/test15.sh
-rw-r--r-- root/root       106 2015-10-28 21:48 work/test16.sh
-rw-r--r-- root/root      3570 2015-10-28 22:09 work/test17.sh
-rw-r--r-- root/root        88 2015-11-15 08:56 work/test18.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar vf /tmp/tar_test.tar.gz --delete work/*.py*
[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root        96 2015-10-14 09:00 work/test10.sh
-rw-r--r-- root/root      1168 2015-10-28 20:24 work/test11.sh
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root      1276 2015-10-28 20:49 work/test13.sh
-rw-r--r-- root/root     64363 2015-10-28 21:04 work/test14.sh
-rw-r--r-- root/root      4871 2015-10-28 21:19 work/test15.sh
-rw-r--r-- root/root       106 2015-10-28 21:48 work/test16.sh
-rw-r--r-- root/root      3570 2015-10-28 22:09 work/test17.sh
-rw-r--r-- root/root        88 2015-11-15 08:56 work/test18.sh

 

8.アーカイブファイル作成時に特定のファイルを除外する

アーカイブファイルを作成する際、ディレクトリを指定して再帰的に指定するが、特定のサブディレクトリだけは含めないようにしたい事があるだろう。
そんなときは、「-–exclude」オプションもしくは「-X」オプションを使用すると良いだろう。

tar cvf 作成するアーカイブファイルPATH --exclude 除外ディレクトリのPATH アーカイブ対象ディレクトリ # 除外対象をコマンドで指定する場合
tar cvf 作成するアーカイブファイルPATH -X 除外ディレクトリのPATHを書いたファイル アーカイブ対象ディレクトリ # 除外対象をファイルに記述する場合

20151112_000003

[root@test-centos7 ~]# find /work8 -type d
/work8
/work8/work8-1
/work8/work8-1/8-1-2
/work8/work8-1/8-1-3
/work8/work8-1/8-1-4
/work8/work8-2
/work8/work8-2/8-2-4
/work8/work8-2/8-2-2
/work8/work8-3
/work8/work8-4
/work8/work8-4/8-4-2
/work8/work8-4/8-4-1
/work8/work8-4/8-4-7
/work8/work8-5
/work8/work8-6
[root@test-centos7 ~]# tar czvf /tmp/test8.tar.gz --exclude /work8/work8-1 /work8
tar: メンバ名から先頭の `/' を取り除きます
/work8/
/work8/work8-2/
/work8/work8-2/8-2-4/
/work8/work8-2/8-2-2/
/work8/work8-3/
/work8/work8-4/
/work8/work8-4/8-4-2/
/work8/work8-4/8-4-1/
/work8/work8-4/8-4-7/
/work8/work8-5/
/work8/work8-6/

 

9.アーカイブファイル内のPATHで、ワイルドカードやパターンを指定する

アーカイブファイル内のファイルやディレクトリを指定する際、色々な指定方法を使う事が出来る。

  • –anchored … ファイル名の先頭とパターンが一致
  • –ignore-case … 大文字小文字を無視
  • –no-anchored … 任意の ‘/’ 以降にパターンが一致(標準で除外)
  • –no-ignore-case … 大文字小文字を考慮して一致 (標準)
  • –no-wildcards … 逐語的文字列一致
  • –no-wildcards-match-slash … ワイルドカードが ‘/’に一致しない
  • –wildcards … use wildcards (default)
  • –wildcards-match-slash … ワイルドカードが ‘/’ に一致(標準で除外)

基本的にはワイルドカード(*)が有効になっているので、それで指定すると良いだろう。

 

10.アーカイブファイルと実際のファイルの差異を確認する

アーカイブファイルと実際のファイルの差異(といっても、ファイルサイズや最終更新日での比較だが)を確認する場合、「d」オプションを付与すると良いだろう。
そのまま実行するとカレントディレクトリ配下のファイルと比較するので、「-C」で比較先のディレクトリを指定すると良い。

tar dvf 比較するアーカイブファイル -C 比較先ディレクトリ

20151125_000014

[root@test-centos7 ~]# pwd
/root
[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root        96 2015-10-14 09:00 work/test10.sh
-rw-r--r-- root/root      1168 2015-10-28 20:24 work/test11.sh
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root      1276 2015-10-28 20:49 work/test13.sh
-rw-r--r-- root/root     64363 2015-10-28 21:04 work/test14.sh
-rw-r--r-- root/root      4871 2015-10-28 21:19 work/test15.sh
-rw-r--r-- root/root       106 2015-10-28 21:48 work/test16.sh
-rw-r--r-- root/root      3570 2015-10-28 22:09 work/test17.sh
-rw-r--r-- root/root        88 2015-11-15 08:56 work/test18.sh
[root@test-centos7 ~]# ls -la /work/test1*.sh
-rw-r--r--. 1 root root    96 10月 14 09:00 /work/test10.sh
-rw-r--r--. 1 root root  1174 11月 25 18:40 /work/test11.sh
-rw-r--r--. 1 root root   573 10月 28 20:39 /work/test12.sh
-rw-r--r--. 1 root root  1276 10月 28 20:49 /work/test13.sh
-rw-r--r--. 1 root root 64363 10月 28 21:04 /work/test14.sh
-rw-r--r--. 1 root root  4871 10月 28 21:19 /work/test15.sh
-rw-r--r--. 1 root root   106 10月 28 21:48 /work/test16.sh
-rw-r--r--. 1 root root  3570 10月 28 22:09 /work/test17.sh
-rw-r--r--. 1 root root    88 11月 15 08:56 /work/test18.sh
[root@test-centos7 ~]# tar dvf /tmp/tar_test.tar.gz -C /
work/test12.sh
work/test10.sh
work/test11.sh
work/test11.sh: 最終修正時刻が異なります
work/test11.sh: サイズが異なります
work/test12.sh
work/test13.sh
work/test14.sh
work/test15.sh
work/test16.sh
work/test17.sh
work/test18.sh

 

11.アーカイブファイル内のファイルの中身を参照する

アーカイブファイル内のファイルを参照する場合は、「O」オプションを用いる。
中のファイルを指定しないとアーカイブファイル全体を参照してしまうので、必要に応じて中身を指定する。

tar xOf 対象のアーカイブファイル [参照するアーカイブファイル内のファイル]

20151125_000015

[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root        96 2015-10-14 09:00 work/test10.sh
-rw-r--r-- root/root      1168 2015-10-28 20:24 work/test11.sh
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root      1276 2015-10-28 20:49 work/test13.sh
-rw-r--r-- root/root     64363 2015-10-28 21:04 work/test14.sh
-rw-r--r-- root/root      4871 2015-10-28 21:19 work/test15.sh
-rw-r--r-- root/root       106 2015-10-28 21:48 work/test16.sh
-rw-r--r-- root/root      3570 2015-10-28 22:09 work/test17.sh
-rw-r--r-- root/root        88 2015-11-15 08:56 work/test18.sh
[root@test-centos7 ~]# tar xOf /tmp/tar_test.tar.gz work/test18.sh
get_date=`date +%d -d '1 day'`
if [ $get_date = "01" ];then
    echo "月末です"
fi

 

これを使うことで、アーカイブファイルの中身(ログファイルなど)に対しgrepを行う事も出来る。

20151125_000016

 

12.展開したファイルを別のコマンドに引き渡す

展開したファイルを別のコマンドで処理する場合、「–to-command=」オプションを使う。
なお、コマンドに引き渡した場合はファイルの展開は行われないので注意する。

tar xvf 展開するアーカイブファイル --to-command=コマンド

引き渡すコマンド内で使用できる主な変数は以下。

  • $TAR_MODE … アーカイブファイル内のパーミッション
  • $TAR_FILENAME … アーカイブファイル内のファイル名
  • $TAR_UNAME … アーカイブファイル内のファイルのオーナー名
  • $TAR_UID … アーカイブファイル内のファイルのオーナーID
  • $TAR_GNAME … アーカイブファイル内のファイルのグループ名
  • $TAR_GID … アーカイブファイル内のファイルのグループID
  • $TAR_SIZE … アーカイブファイル内のファイルサイズ

 

例えば、アーカイブファイルから展開するファイルPATHを取得して、オリジナルファイルをlsで見る場合だと、以下のようにコマンドを実行する。

20151125_000017

[root@test-centos7 ~]# tar tvf /tmp/tar_test.tar.gz
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root        96 2015-10-14 09:00 work/test10.sh
-rw-r--r-- root/root      1168 2015-10-28 20:24 work/test11.sh
-rw-r--r-- root/root       573 2015-10-28 20:39 work/test12.sh
-rw-r--r-- root/root      1276 2015-10-28 20:49 work/test13.sh
-rw-r--r-- root/root     64363 2015-10-28 21:04 work/test14.sh
-rw-r--r-- root/root      4871 2015-10-28 21:19 work/test15.sh
-rw-r--r-- root/root       106 2015-10-28 21:48 work/test16.sh
-rw-r--r-- root/root      3570 2015-10-28 22:09 work/test17.sh
-rw-r--r-- root/root        88 2015-11-15 08:56 work/test18.sh
[root@test-centos7 ~]#
[root@test-centos7 ~]# tar xvf /tmp/tar_test.tar.gz --to-command='ls -la /$TAR_FILENAME'
work/test12.sh
-rw-r--r--. 1 root root 573 10月 28 20:39 /work/test12.sh
work/test10.sh
-rw-r--r--. 1 root root 96 10月 14 09:00 /work/test10.sh
work/test11.sh
-rw-r--r--. 1 root root 1174 11月 25 18:40 /work/test11.sh
work/test12.sh
-rw-r--r--. 1 root root 573 10月 28 20:39 /work/test12.sh
work/test13.sh
-rw-r--r--. 1 root root 1276 10月 28 20:49 /work/test13.sh
work/test14.sh
-rw-r--r--. 1 root root 64363 10月 28 21:04 /work/test14.sh
work/test15.sh
-rw-r--r--. 1 root root 4871 10月 28 21:19 /work/test15.sh
work/test16.sh
-rw-r--r--. 1 root root 106 10月 28 21:48 /work/test16.sh
work/test17.sh
-rw-r--r--. 1 root root 3570 10月 28 22:09 /work/test17.sh
work/test18.sh
-rw-r--r--. 1 root root 88 11月 15 08:56 /work/test18.sh

 

13.sshコマンドと組み合わせる

sshコマンドと組み合わせる事で、ローカルのファイルをアーカイブした状態でscp転送したり、その逆も行う事ができる。
詳細についてはリンク先で記述しているので、そちらを参照してもらいたい。

#【ローカル→リモート】ローカルでファイル・フォルダを圧縮し、リモートでアーカイブファイルとして保持させる
tar zcvf - /アーカイブ化したいディレクトリのパス | ssh ユーザ名@リモートホスト "cat &gt; /リモート側で作成するアーカイブ・ファイルのパス

#【ローカル→リモート】ローカルのアーカイブファイルをリモートで解凍する
ssh ユーザ名@リモートホスト "tar zxvf -C リモート側で展開させたいフォルダ -" &lt; /リモート側で解凍させたいアーカイブファイルのパス #【リモート→ローカル】リモートでファイル・フォルダを圧縮し、ローカルでアーカイブファイルとして保持させる ssh ユーザ名@リモートホスト "tar -cf - /アーカイブ化したいディレクトリのパス" | gzip &gt; /ローカル側で作成するアーカイブ・ファイルのパス

#【リモート→ローカル】リモートのアーカイブファイルをローカルで解凍する
ssh ユーザ名@リモートホスト "cat /ローカル側で解凍させたいアーカイブファイル" | tar zxvf - -C ローカル側で展開させたいフォルダ

 

以上、この他にも使い方は色々あると思うが、最低限この辺を覚えておけばそんなに困らないであろう。

初心者のためのGNUオクターブ入門: コマンドとグラフィックスの分かりやすい説明 初心者のためのGNUオクターブ入門: コマンドとグラフィックスの分かりやすい説明
Viewing all 743 articles
Browse latest View live