2014/03/27

LDAP 登録用スクリプト

以前、某社内のユーザ管理を ldap 化した際に作成した ldap 登録用の ldif ファイルを生成するスクリプト。
漢字の名字と名前を入力すると kakashi を利用して ひらがなの名字、名前、ローマ字の名字、名前を自動的に取得し ldap 登録用の ldif ファイルを生成して ldap 登録まで自動で行う。
当初は csv 型式のファイルから必要な情報を取得して 連続で ldap に登録するバッチスクリプトとして作成したのだが、 初期登録が完了した後はたまに発生するユーザの追加処理にのみ使用するので 対話的に実行するコマンドに作り直した。

漢字をひらがな/ローマ字に変換するために kakashinkf が必要になる。
漢字のよみは自動では完全には取得できないので変換した値を確認する様にしている。 ローマ字の氏名は私の趣味で名字は全て大文字、名前はキャピタライズとしている。

  1#!/bin/sh
  2# All rights reserved, copyright (C) 2014, Mitzyuki IMAIZUMI
  3#
  4
  5# ldap 用設定
  6passwd="password"
  7org="dc=example,dc=com"
  8
  9# コマンド定義
 10id="`/usr/bin/id -u`"
 11kakasi=/usr/bin/kakasi
 12slappasswd="/usr/sbin/slappasswd -h {md5}"
 13toutf="/usr/bin/nkf -w"
 14toeuc="/usr/bin/nkf -e"
 15ldapadd="/usr/bin/ldapadd -x -D cn=Manager,${org}"
 16ldappasswd="/usr/bin/ldappasswd -x -D cn=Manager,${org}"
 17ldapsearch="/usr/bin/ldapsearch -LL -x -D cn=Manager,${org}"
 18
 19# uid 格納ファイル
 20uidnum=/etc/uid
 21
 22# OU 選択肢
 23oulist="Board Sales Develop Affair"
 24
 25# 入力用タイトル
 26_uid="ユーザID"
 27_sn="漢字名字"
 28_gn="漢字名前"
 29_hsn="名字よみ"
 30_hgn="名前よみ"
 31_tel="内線番号"
 32_ou="所属"
 33
 34#
 35# 汎用入力処理
 36#   $1: 入力された値を格納する変数名
 37#   $2: 必須フラグ
 38#
 39getans()
 40{
 41
 42    title=`eval "echo \\$_$1"`
 43    var=$1
 44    require=${2:-true}
 45
 46    while true
 47    do
 48        echo -n "${title} を入力して下さい: "
 49        read ans
 50
 51        if [ -z "${ans}" ]
 52        then
 53            if ${require}
 54            then
 55                echo "${title} の入力は必須です"
 56            else
 57                echo "${titoe} なし"
 58                break
 59            fi
 60        else
 61            break
 62        fi
 63    done
 64
 65    eval "$var=${ans}"
 66            
 67}
 68
 69#
 70# カナ確認/入力処理
 71#   $1: 入力された値を格納する変数名
 72#
 73getkana()
 74{
 75
 76    title=`eval "echo \\$_$1"`
 77    var=$1
 78
 79    echo -n "${title} は \"${2}\" で正しいですか?([y]/n): "
 80    read ans
 81    if [ "${ans}" = "n" ]
 82    then
 83        getans ${var}
 84    else
 85        eval "$var=${2}"
 86    fi
 87
 88}
 89
 90#
 91# 所属選択処理
 92#   $1: 入力された値を格納する変数名
 93#
 94getou()
 95{
 96
 97    title=`eval "echo \\$_$1"`
 98    var=$1
 99
100    while true
101    do
102        i=1
103        set ${oulist}
104        for o
105        do
106            echo "${i} ) ${o}"
107            i=`expr ${i} + 1`
108        done
109        echo -n "${title} を選択して下さい: "
110        read ans
111        if [ "${ans}" -ge 1 -a "${ans}" -lt $i ]
112        then
113            eval "$var=\${$ans}"
114            break
115        else
116            echo "入力が不正です"
117        fi
118    done
119
120}
121
122#
123# UID 取得処理
124#
125getuid()
126{
127
128    num=`cat ${uidnum}`
129    expr ${num} + 1 > ${uidnum}
130
131}
132
133#
134# People 用 ldif ファイルの生成
135#
136ladduser()
137{
138
139    cat <<-EOF | ${toutf}
140        dn:             uid=${uid},ou=People,${org}
141        uid:            ${uid}
142        objectclass:    posixAccount
143        objectclass:    top
144        objectclass:    shadowAccount
145        objectclass:    inetOrgPerson
146        cn:             ${sn} ${gn}
147        cn:             ${hsn} ${hgn}
148        cn:             ${rgn} ${rsn}
149        sn:             ${rsn}
150        givenname:      ${rgn}
151        mail:           ${uid}@example.com
152        o:              Example, Inc.
153        ou:             ${ou}
154        loginShell:     /bin/bash
155        uidNumber:      ${num}
156        gidNumber:      ${num}
157        homeDirectory:  /home/${uid}
158        gecos:          ${rgn} ${rsn}
159EOF
160    test -n "${tel}" && echo "telephoneNumber:  ${tel}"
161    echo
162
163}
164
165#
166# Group 用 ldif ファイルの生成
167#
168laddgroup()
169{
170
171    cat <<-EOF | ${toutf}
172        dn:             cn=${uid},ou=Group,${org}
173        objectclass:    posixGroup
174        objectclass:    top
175        cn:             ${uid}
176        userPassword:   {crypt}x
177        gidNumber:      ${num}
178        memberUid:      ${uid}
179
180EOF
181
182}
183
184#
185# ID が既に使用済みか確認する
186#   $1: ID
187#
188existldap()
189{
190
191    if ! egrep -q "^${1}:" /etc/passwd
192    then
193        return `${ldapsearch} uid=${1} -w ${passwd} | grep uid | wc -l`
194    else
195        return 1
196    fi
197
198}
199
200#
201# メイン処理
202#
203if [ "${id}" != "0" ]
204then
205    echo "root にて実行して下さい" 1>&2
206    exit 255
207fi
208
209# 情報入力
210while true
211do
212    while true
213    do
214        getans "uid"
215        if existldap ${uid}
216        then
217            break
218        fi
219        echo  "${uid} は既に使用されています" 1>&2
220    done
221    getans "sn"
222    getans "gn"
223    gettel "tel" false
224    getkana "hsn" "`echo ${sn} | ${toeuc} | ${kakasi} -JH | ${toutf}`"
225    getkana "hgn" "`echo ${gn} | ${toeuc} | ${kakasi} -JH | ${toutf}`"
226    getou "ou"
227
228    echo
229    for i in uid sn gn hsn hgn tel
230    do
231        eval "echo \$_$i: \$$i"
232    done
233
234    echo -n "この情報で正しいですか?([y]/n): "
235    read ans
236    if [ "${ans}" != "n" ]
237    then
238        break
239    fi
240done
241
242# ローマ字表記の名字取得(全て大文字)
243rsn=`echo ${hsn} | ${toeuc} | ${kakasi} -Ha -Ka -Ja -Ea -ka | tr '[a-z]' '[A-Z]'`
244# ローマ字表記の名前取得(キャピタライズ)
245rgn=`echo ${hgn} | ${toeuc} | ${kakasi} -Ha -Ka -Ja -Ea -ka |  awk '{ print toupper(substr($0, 1, 1)) substr($0, 2, length($0) - 1) }'`
246getuid
247# People 登録
248ladduser | ${ldapadd} -w ${passwd}
249# Group 登録
250laddgroup | ${ldapadd} -w ${passwd}
251# パスワード自動生成
252${ldappasswd} uid=${uid},ou=People,${org} -w ${passwd}
    

あまり需要がないとは思うけど折角なので公開してみる。

2014/03/25

キャピタライズ

英単語の先頭を大文字に置換する処理をキャピタライズというが、 このキャピタライズ処理を unix 標準のコマンドで実装しようという話。
置換と言えばまず思い浮かぶのが sed (1) なのだが、 GNU 拡張された sed (1) の場合は簡単に置換が可能なのだが、 FreeBSD の標準の sed (1) では簡単にいかない。

GNU sed の場合
$ echo "foo" | sed 's/\(.\)\(.*\)/\U\1\L\2/g'
Foo
            
GNU 拡張された sed (1) には \U/L という 演算子があるので大文字、小文字変換が簡単に可能である。

FreeBSD 標準の sed の場合
$ echo "foo" | sed 's/\(.\)\(.*\)/\U\1\L\2/g'
UfLoo
            
FreeBSD 標準の sed (1) だと正しく変換されない。

awk を利用した場合
sed (1) ではなく awk (1) を利用すれば FreeBSD でもキャピタライズ処理は簡単にできる。
$ echo "foo" | awk '{ print toupper(substr($0, 1, 1)) substr($0, 2, length($0) - 1) }'
Foo
            
awk (1) には大文字変換関数が実装されているので、 切り出した1文字目を大文字変換すれば簡単に実現できる。
ここまではシェル芸っぽくワンライナーでそれなりに綺麗に実現可能…かな?

FreeBSD で sed を利用した場合
どうしても FreeBSD の sed (1) を利用したい場合、 tr (1) も併用する事にはなるが以下の処理で可能だ。
$ eval `echo "foo" | sed 's/\(.\)\(.*\)/\/bin\/echo -n \1 | tr "[a-z]" "[A-Z]"; echo \2/g'`
Foo
            
sed (1) でtr (1) を利用した置換スクリプトを出力して eval (1) で実行した結果を表示しているのだが もはやネタとしか思えなくもない。
良い子は真似しないで下さい(笑

2014/03/04

C9A4 V6 650 + docomo 携帯での通信設定

CX-5 のメイカー純正カーナビゲーション ALPINE C9A4 V6 650 を docomo の携帯電話と Bluetooth 接続して通信設定をしていたのだが、 先日、携帯電話を変更してからデータ通信が出来なくなっていた。
ナビゲーションと携帯電話は Bluetooth でペアリングが出来ていて 音声通話などは普通に利用できているのだが、 ナビゲーション側から地図データの差分更新などのデータ通信を開始すると 「接続できませんでした」というエラーが表示されてしまい データ通信ができない状況だった。
データ通信のために接続を開始している携帯電話の画面を参照すると mopera.ne.jp に接続しようとして切断されているのが確認できたが、 現在 docomo の携帯によるデータ通信は mopera.net に接続する必要があるので、 以下の操作で C9A4 V6 650 に初期設定されている接続先を mopera.net に変更する事で無事にデータ通信が可能となった。

  1. 画面左下の 設定 ボタンクリック
  2. 画面右上の 設定・編集 をタッチ
  3. 画面右下の Bluetooth設定 をタッチ
  4. Bluetooth機器設定の右にある 変更 をタッチ
  5. 選択リストから利用している Bluetooth 機器(携帯)をタッチ
  6. 画面下の 通信接続先 をタッチ
  7. 選択リストから NTT docomo FOMA / パケット通信 をタッチ
  8. 画面下の 詳細設定 をタッチ
  9. 電話番号の「*99***1#」を「*99***3#」に変更
この操作を行う事でパケット通信の接続先を mopera.ne.jp から mopera.net に変更できる。

なお、データ通信には大量のパケット通信が発生するので パケット通信代が非常に高額になってしまう可能性もあるので、 十分に気をつけて設定する必要がある。


Copyright © Mitzyuki IMAIZUMI 2008,2009. All rights reserved.