ユーザーの一括登録、追加と削除
Mac OS X ServerにはWorkgroup Manager(以下WgM)というソフトが付属していて, ユーザー登録やユーザー環境設定をGUIベースで簡単に行なうことができる。 実際に操作してみると,至れり尽せり,といった感じだ。
でも,毎学期ごとに1000人程度のユーザーについて,追加登録と削除を行なう 必要があるので,それをいちいち手作業でやるのは,ちょっと考えたくない。
幸い,WgMには,テキストファイルに記述されたユーザー情報を一括登録する機能が 備わっているので,WgMが認識してくれるようなファイルを吐き出すようなスクリプト を書いてやれば,割合と簡単に一括ユーザー登録ができる。
そのやり方と,テキストファイルの書式はWgMのマニュアル(http://www.apple.com/jp/server/documentation/ のユーザーの管理)に 書かれているので,それを参考にすればよい。 が,実際には試行錯誤の連続で、かなりの時間を費やすことになった。
ユーザーの一括登録
この端末室の場合、作業の流れはざっと以下のような感じになる:
- 学期の始まりになると、教務担当者はデータベースを操作して、その学期に在学している学生のリストをファイルに保存する。
- それを元にして、各フィールドが
学籍番号, 氏名, 所属, 在籍状況, 初期パスワード
のエクセルファイルを作成する。
- それをCSVファイルで保存する。
- CSVデータを自作のプログラムgen-user-record.rbで処理して得られたデータをWgMで「読み込む」(WgMの「サーバー」メニューから「読み込み」)
▼CSVファイルからWgMが認識するデータを生成するスクリプト:gen-user-record.rb
#!/usr/bin/ruby $KCODE="EUC" require "csv" require "nkf" require "iconv" class UserRecord def initialize @server = 'xxxx.xxxx.ac.jp' @volume = 'home' @gid = 1000 @usershell = '/bin/bash' @diskquota = '209715200' end def genuid(str) if str.length < 8 then uid = str.gsub(/([0-9][0-9])(\w)([0-9]*)/) { "19" + $1 + "0" + $3 } else uid = str.gsub(/(\w)(\w)(\w)(\w)([0-9]*)/) { year = "" course = "" case $1 when "9" then year = "199" + $2 when "a" then year = "200" + $2 when "b" then year = "201" + $2 else end case $4 when "b" then course = "1" when "m" then course = "2" when "d" then course = "3" else course = "0" end year + course + $5 } end return uid end def scancsv(csvfile) file = File.open(csvfile,'rb') # Excel for Mac generates \r as end of line reader = CSV::Reader.create(file, ?, , ?\r ) reader.each do |row| gakuseki = row[0].to_str.downcase longname = NKF.nkf("-e",row[1].to_str) course = NKF.nkf("-e",row[2].to_str) status = NKF.nkf("-e",row[3].to_str) password = row[4].to_str if /在学/ =~ status then self.gen_user_record(gakuseki,longname,course,password) end end reader.close file.close end def gen_user_record(gakuseki,longname,course,password) names = longname.split(/[\s ]/) homedir = "<home_dir><url>afp\\\://#{@server}/#{@volume}</url><path>#{gakuseki}</path></home_dir>" nfshomedir = "/Network/Servers/#{@server}/Volumes/#{@volume}/#{gakuseki}" uniqid = genuid(gakuseki) print "#{gakuseki}:" print 'dsAuthMethodStandard\:dsAuthClearText:' print "#{password}:" print "#{uniqid}:" print "#{@gid}:" print Iconv.iconv("UTF-8","eucJP","#{course}:") print Iconv.iconv("UTF-8","eucJP","#{longname}:") print "#{homedir}:" print "#{@diskquota}:" print "#{@usershell}:" print Iconv.iconv("UTF-8","eucJP","#{names[1]}:") print Iconv.iconv("UTF-8","eucJP","#{names[0]}:") puts nfshomedir end def print_header print '0x0A 0x5C 0x3A 0x2C dsRecTypeStandard:Users 13 ' print 'dsAttrTypeStandard:RecordName ' print 'dsAttrTypeStandard:AuthMethod ' print 'dsAttrTypeStandard:Password ' print 'dsAttrTypeStandard:UniqueID ' print 'dsAttrTypeStandard:PrimaryGroupID ' print 'dsAttrTypeStandard:Comment ' print 'dsAttrTypeStandard:RealName ' print 'dsAttrTypeStandard:HomeDirectory ' print 'dsAttrTypeStandard:HomeDirectoryQuota ' print 'dsAttrTypeStandard:UserShell ' print 'dsAttrTypeStandard:FirstName ' print 'dsAttrTypeStandard:LastName ' puts 'dsAttrTypeStandard:NFSHomeDirectory ' end end def showhelp print <<-ENDOFHELP 使い方: 1. 学籍番号,学生氏名漢字,所属,学籍状態,初期パスワード の順で保存されたCSVファイルを用意(Mac版エクセルを使用) 学籍状態のフィールドが「在学」のレコードのみ登録 2. gen-user-record.rb CSVファイル名 > 結果ファイル で保存 3. 結果ファイルを Workgroup Manager.app でインポート メモ: ・Mac版Excelの出力するCSVファイルは、改行が\\r 文字コードがShiftJIS ・このツールの出力は、改行が\\n 文字コードはUTF-8 ・一部の漢字はCSVで保存した時点で化けてしまうことがある(「高」の別字など) ・うまく登録できないときは新規ユーザー分を「既存のレコードを上書きする」で試してみる ENDOFHELP end filename = ARGV.shift if filename.nil? || /\A\-h/ =~ filename then showhelp exit end if FileTest.exist?(filename) then userrec = UserRecord.new userrec.print_header userrec.scancsv(filename) end
Macのエクセルは改行コードがCR(だけ)なので、RubyのCSVクラスでフツーに読み込むと ちゃんと動作しない。そこでReaderを定義して、改行コードと区切り文字を明示的に与えている。
ユーザー登録ではまる
このスクリプトの動作は,大体こんな感じである:
- この大学の学籍番号は a5sb1234 のような形式になっている。この学籍番号をそのままユーザーID(レコード名)として使う。また、学籍番号から将来も含め重複が生じないようにUniqueIDを生成する。
- パスワードはクリアテキストであらかじめ用意しておく。
- Mac用のエクセルは,CVSファイルの出力がShiftJISコードで改行コードが?r。WMが認識するのはUTF-8と?nなので,ちゃんと変換する。
- その他,AFP用のホームディレクトリやdiskquota, shellなども記述したファイルを,WgMのマニュアルにある書式で出力する。
いくつかの試行錯誤の後,マニュアルに書いてある通り(のはず)の出力が得られるようになったので,WgMにえいやっと「読み込み」をさせてみるも,どうも様子がおかしい。
読み込みが終了しても,登録したはずのユーザーの中にログインできないものが多数ある。うまくいかなかったユーザーのディレクトリをいじろうとしてもエラーが出る。そのエラーは(主に)
eDSAuthFailed エラーコード:-14090
だった。これが出はじめると,どうにもこうにもおかしな状態になって,全くお手上げだ。
困ってしまい,いろいろと調べると,Appleの英語のサイトのdiscussion boardに同じ症状を訴えている記事が見つかった。どうもバグっぽい。そこに書いてあった対処法は以下のとおり:
- シングルユーザーモードで立ち上げる(Appleキー+Sを押して立ち上げる)
- mount -uw / (ファイルシステムをマウントする)
- cd /var/db/authserver
- rm authserverfree (パスワードサーバーが新しいスロットを割り当てるようにする)
- rm *overflow (オーバーフローファイルを全て削除)
- exit でマルチユーザーモードに
- それでもうまく認証されないユーザーは削除してもう一度作成する
実はこの記事が投稿されたのは,問題に悩ませられはじめてから随分と経ってからで、 問題の発生時には知るよしもなかった。 そのときは、しかたなくディレクトリーサービスを一旦止め、再設定からはじめて、 何とか期限に間に合わせたのだった。 かなりの時間を費やした割には、何かが得られた気分のしない、 とても後味の悪い一件であった。
Mac用エクセルの使いにくさ
当初はユーザー登録用のデータの作成(WgMに読み込ませるまで)は、すべて エクセルのマクロで行うつもりだった。 そして、その開発を某社にお願いしたのだった。
ところが、Mac版のエクセルは
- セルのデータをファイルに保存する際に、ShiftJISに変換される。 WMが認識するのはUTF-8なのでUTF-8に変換しようと試みたが、その機能が見当たらない。Windows版にはUTF-8への変換用の関数が用意されているのに、Mac版にはそれがない。
- 上記と関係して、エクセルの中では正しく表示される漢字の中に、保存したとたんに化けてしまうものがあった(ShiftJISに変換できない漢字)。
- 行末コードがCRのみなので、後からLFに変換する必要があった
など、この目的にはなんだかとても使いにくい代物であることが、後から判ったのだ。そこで、Mac OSには標準でインストールされているRubyを使って、自分でスクリプトを書くことにしたのだった。
ユーザー(学生)の更新
学期が変わると、新入学や卒業などに応じて、アカウントを追加したり削除する必要 が生じる。 そこで、古いユーザー一覧と新しいユーザー一覧を比較して、削除すべきユーザー(つまり、古いデータにはあるが新しいデータには存在しないレコード)だけを抽出するスクリプトも書いてみた。
Rubyには配列の「差」を取る機能が内蔵されているので、プログラムの心臓部はたった1行で済んでしまった。
▼二つのCSVを較べて、消去すべきユーザーを捜すスクリプト:diff-users.rb
ついでに、削除すべきユーザーリストをファイルから読み込んで、ディレクトリから削除し、ついでにホームディレクトリも移動するスクリプトも作っておいた。変数passwordにはrootのパスワードを入れておく。なお、この例は実際は必要なコマンドを画面に出力するだけ。
▼ユーザーを消去する(コマンドをはき出す)スクリプト:delete-users.rb
これら2つのスクリプトは、書いてみただけで、まだ本番で使用していないので、何か深刻な問題を含んでいる可能性があります。使用する場合はそれぞれの責任でお願いします。
▼二つのCSVファイルを比較して新規登録ユーザー分だけCSVではき出すスクリプト:list-new-user.rb
ユーザー更新の作業の流れ
- 新規ユーザーの登録
- 事務から登録すべきデータのエクセルファイルが送られてくる
- Mac用のエクセルでCSV形式で保存する
- list-new-user.rb 新年度のCSV 前年度のCSV > 新規登録用CSV
- gen-user-record.rb 新規登録用CSV > 新規登録データ
- WgMのサーバー/読み込みで新規登録データを選択。重複の処理方法は「重複を確認しない」。確認するとうまく行かないケースあり。ユーザーのプリセットも設定
- 旧ユーザーの削除
- diff-users.rb 新年度のCSV 前年度のCSV > 削除IDリスト
- delete-users.rbのパスワード欄を設定しておく
- delete-users.rb 削除IDリスト > 削除シェルスクリプト
- sh 削除シェルスクリプト (1回もログインしていないユーザーにはホームディレクトリが存在しないので、移動の際にエラーが出るが、無視)
その他の注意
ピリオドやドル記号はユーザー名(ショート名)には使えない。
Keyword(s):[WorkGroupManager]
References:[frontpage] [Mac OS X Serverで作る 小さな計算機室]