上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
2016.12.23 今さらCentOS6
仕事でLinuxを使うことがそれなりにあるのだけど・・・
CentOSをVirtualBOXにインストールした、その手順のメモ書き。
CentOSといっても、最新のではなくて一つ前のメジャーバージョン、6.8Finalというやつ。
なぜ今さらCentOS6か、というと本番環境はRHELで評価環境と言うかデバッグ環境で必要になったから。


x86のDVD用イメージを2つダウンロードしてきて(オヂサンはftp.jaist.ac.jpから落してきた)からが本番。
VirtualBOXで操作しなければ行けないのは3つ。
・タイプLinuxにしてから、バージョンをRedHatもしくはFedoraにする(CentOSという項目は無い)
・CPUの設定で「PAE/NXを有効化」にする
・ストレージの設定で仮想HDDの容量をデフォルトの8Gから32G以上にすること。
あとはデフォルト設定でOK。
使用するメモリをギリギリまで減らすなら仮想PCへのインストールが終わってから。
インストール時には最低768(デフォルト)以上にしておくのが吉。

仮想PC立ち上げてインストーラーが動き出したら、言語は日本語で。
用途はDesktopかSoftwareDevelop(オヂサン、いちおうプログラマーだから)で。
このとき、オプション設定で必要なアプリを先に選んでおくといい。
あとから入れるのはWindowsに慣れてると「あ゛ぁ!?」ってなることが多い(パッケージの依存関係とか)
Windowsだと依存関係というと、ほとんどがVBランタイムとか.NetFrameworkのバージョンが~という程度で済んじゃうから。
あとはデフォルトのままとにかくインストール(設定項目ほとんどなし、ユーザーアカウントぐらい)。

CentOSが立ち上がってユーザーアカウントでログインしたら真っ先にやること。
1)ネットワーク(VBOX側)とIPアドレス(ゲストOS側)の設定
2)YUMレポジトリの変更(そのままだと何も出来ない)
3)Javaのバージョンアップ(先に古いJava消すと依存関係のせいで色々おかしくなるので止めましょう・・・)
必要なら
4)共有フォルダの設定

オヂサンはそこからNetBeansのインストールするぐらいで事が足りるので、あとはIPアドレスの設定弄ったりする程度なのだけど。

参考にしたページ
サーバーワールドさん
VirtualBOX Maniaさん
スポンサーサイト
2016.03.19 IT技術者(笑
複数拠点をインターネットVPNで繋いでる環境で、接続元の端末をホストで識別する、という当たり前の事をやることになったのだけど・・・
オヂサンが50の手習いとばかりに入門書を片手に現地の施工図と首っ引きで試験用にネットワークを組んでみた。
そこから実機テストなのだけど、サーバアプリの担当者が「IPが全部同じだ! 環境がオカシイ!!」と騒ぎ出したのが23時過ぎ。
イロイロ調べて環境は現地とほぼ同じという保障が取れたのが4時過ぎ。
で、サーバアプリの問題だろ、というので寝てる担当者を起こして問いただした。
サーバーはXAMPPという、WindowsでWebサーバーとデータベースとを使うためのメジャーな環境で、端末はAndroidの専用アプリといいつつ、内部で標準ブラウザを呼び出してる手抜きもといOSのバージョンに依存しない作り方したアプリ。
で、詳しく聞けば「サーバでPHPのコマンドでIPとるのがあるので、端末はただアクセスするだけ」と言う。

サーバアプリの担当者は初めて組む奴なのだけど、専門外のオヂサンですら知ってる基礎的なことを知らない。
今回は、Webサーバ(といっても普通のパソコンで、部品の耐久性が高いぐらいの違いしかない)のページを見に来たパソコンのIPアドレスを記録するんだけど、そのために使ったコマンドで取れるIPが全てVPNルータのアドレスになるもの。
既存のネットワークを使うので設定は変更できないので、他の方法を使うしかないのだけど、サーバアプリ担当者が不機嫌に「ネットワークが悪い、俺のせいじゃない」とマジで言うので思い切りぶん殴った。物理で。
マヂに切れたですよー。

Webサーバにアクセスするプロトコルは?と質問して「HTTPかHTTPSじゃないの?」というのは正解。
でもそれは不正解。
HTTPだHTTPSだというのは「コンピュータとコンピュータの間で通信路が確保された状態」でやり取りされるデータの形式を決めたもの。
電話にたとえるなら、電話がつながった後で「日本語で話すか、スワヒリ語で話すか、エスペラント語をつかうのか」というレベル。
「相手と動会話するか」のプロトコルで「相手とどう繋ぐか」という今回の問題とは考えるレイヤーが違う。

OSI参照モデル、という考え方があって「物理的に隣の相手」との繋ぎ方を決めたレイヤー1~3まで、と最終的につながる相手との繋ぎ方を決めたレイヤー4以上というごく大雑把かつ乱暴なわけ方がある。
んで、くだんのPHPのコマンドと言うのがレイヤー3で使われる「IP」と言う決まりで使われる装置を識別するマーク、つまりIPアドレスでいわゆる「おなじLANの中だけで通じるアドレス」。
すこしばかりネットワークがわかっていれば誰でも知ってる常識だったりする。
最初からきちんと仕様と、PHPのコマンドを理解していれば使わなかったものを使っといて「俺は悪くない」と本気で言うあたりお粗末過ぎる。

要求は「どの端末からアクセスされたか記録すること」ということで、IPアドレスで記録しろ、とはいってない。
急遽、端末側のアプリを修正して端末毎にIDを割り振ることにして・・・という余計な仕事ができた。

朝一に来たマネージャにその報告を愚痴と共にしたら無言でため息をつかれた。
失った6時間のためにマネージャ氏は徹夜になるとのこと。
昨日、若い同業者とちょっとばかり、プログラムを書く上で必要なものは何か、というテーマってほどでもないけど、で話し込んだ。
お互い、酒が入って「ヒトサマの書いたプログラムなんか直せるかヴラー!」とクダを巻いてきただけども言う。
若いといっても中年の入り口に差し掛かった微妙なお年頃の中堅なのだけど。

最近はクラス化された言語ばかりなので1つのメソッドが巨大になるというのは少ないのだけど、その若い同業者がぶち当たったのはコメントを取り除いてなんと2千行を超えていたという。
if文ネストが7段とか8段とか、こぴぺされた同じ処理が繰り返し出現するとか、そりゃひどいソースだったとのこと。
聞いていれば、書き方もそうだけど、そのメソッド、本来は別々に書くべき2つか3つの異なる処理をひとまとめにした素晴らしいモノだった。
最近の仕事は通信とは切っても切れないのでどうしても通信を意識しないといけない部分がでてくる。
HTTPつかってXMLベースでデータをやり取りすると非常に楽ができるのだけど、組込みなんかだとWebサーバー立てるほうが面倒だったりする場合がある。
なんでかっていうと、装置用のWebサーバーが非常に高かったり、無かったり、そもそもWebサーバー動かすには貧弱なマシンだったりする。
今回もWebサーバー使えない装置との通信で使う部分だった。
1バイト目にデータの種類を示す値を、2バイト目には・・・のようにきっちりと仕様を決めてあるのだけど、なにせその装置との間でやりとりするのは100種類を超えるのでバリエーションが多い。
今回はそのバリエーションを増やすお仕事なのだけど一つや二つではなくて10ぐらい増える。
当然、それにかかわる処理も多くなるのだけど・・・ひとつのメソッドで全部やろうとしていたという。
で、「ヒトサマの書いたプログラムなんか直せるかヴラー!」になるわけだけど、そいつはどうしたかと言うと、そのメソッドはごっそり全部書き直してしまった。
内部で4~5個に分割して、判りやすく無駄を省いて書き直したら性能も15%アップとのこと。
テスト仕様書も平行して書いても1週間でおわったから、書いた量そのものは大してないはず。

元のプログラムは典型的なスパゲッティプログラミングだったらしい。
「読みやすく、判り易く、書き換えしやすいのが良いプログラム」が常識的に言われるようになって既に四半世紀は経つ。
オヂサンがやってるような組込みなんかだと「10年20年先でもプログラムわかるように」といわれるのが当たり前。
建物に例えると、プレハブ式のユニット構造な建物がいい。
キッチンにバスタブは要らないし下駄箱だって不要、玄関に便座は要らない、トイレに冷蔵庫は置かない。

必要なものを、必要なところに、必要なだけ。

これさえ守れば「酷い」といわれるようなものは作らないと思うんだけどねぇ。
「ひさびさにプログラム書いたなー、どっかにメモしないとわすれるなー」ってここに書くことに。
Blogをメモ代わりにしても、いいよね?

さて、本題。
Excelで複数のシートをひとつにまとめる必要が出てきたんだけどVLOOKUPとか使ってもいいんだけど単純にシートの内容をマージというか、「伝票にあたるシートの内容で台帳にあたるシートの内容を上書きしたい」という要望が出てきた。
例によって「人力マクロ」でいちいちやってたんだけど自動化するにあたってExcelVBAで実現することにした。
で、ある行をインデックスにして、インデックス行が特定の文字列になっているのをキー列にするんだけど、データの生成もとのせいでインデックス行の並びも含まれる項目も統一できてない。
「あ~、添え字に文字列していできりゃ楽なのにな~」という同僚の呟きがもれて、よし、それなら作ってしまえ、と。

シート1と2をマージするときはインデックスにする行にあるのは「単価」「個数」「販売先」みたいな文字列。
そのまま「Sheets("シート2").Cells(5,"単価")=Sheets("シート1").Cells(5,"単価")」見たいにはかけない。
”単価”っていう内容のセルがシート1は何番目、シート2は何番目、だからシート2の~とごにょごにょやらないけない。
つまりは「文字列を一意の数値に置き換えるメカニズム」になる。
単純に「文字列と列番号を紐付けた配列つくろう」っとなったけど、VBAだとちょっと面倒だった。

C#や、PHP、Rubyなんかには配列の添え字に直接文字列を書くことができる。

a = datas('売り上げ')

とか

a = datas["売り上げ"]

見たいに。
これとニアリーイコールなことを手軽にVBAでやりたいな、と。
しかも後々改修かかってもオヂサンに回ってこないような誰にでもわかるように・・・。

妥協を重ねて
a = Sheets("シート1").Cells(y, GetValue(配列1,"売り上げ"))
Sheets("シート2").Cells(y, GetValue(配列2,"売り上げ")) = a
のように使えるプロシージャを用意することに。

本当はB木でハッシュ関数なんか使ってキー値の大小比較を高速にするとか良いんだけど、バイナリサーチ+インサートソートという手抜きで実装した。
まだバグがのこってるけど、ひと段落ついたからメモ書きで残しておく。

Public Type 配列要素
  keys As Variant
  values As Variant
  index As Long
End Type

Public Function 配列作成() As 配列要素()
  Dim rtc() As 配列要素
  ReDim rtc(0)
  rtc(0).index = -1 ' 番兵
  配列作成 = rtc
End Function

Public Function 配列値設定(s() As 配列要素, key As Variant, val As Variant) As 配列要素()
  Dim cnt As Long
  Dim pos As Long
  Dim posMax As Long
  Dim posMin As Long
  Dim posMid As Long
  posMax = UBound(s)
  posMin = LBound(s)
  If s(posMin).index < 0 Then
    s(posMin).keys = key
    s(posMin).values = val
    s(posMin).index = posMin
    配列値設定 = s
    Exit Function
  Else
    Do While (posMax - posMin > 5)
      posMid = (posMin + posMax) / 2
      If (s(posMid).keys < key) Then
        posMin = posMid
      Else
        posMax = posMid
      End If
    Loop
    For pos = posMin To posMax
      If s(pos).keys = key Then
        s(pos).values = val
        配列値設定 = s
        Exit Function
      End If
    Next
  End If
  cnt = UBound(s) - LBound(s) + 1
  ReDim Preserve s(cnt)
  s(cnt).index = cnt
  s(cnt).keys = key
  s(cnt).values = val
  Call 配列ソート(s)
  配列値設定 = s
End Function

Private Function 配列ソート(s() As 配列要素) As 配列要素()
  Dim idx1 As Long
  Dim idx2 As Long
  Dim idx3 As Long
  Dim cnt As Long
  Dim t As 配列要素
  Dim looping As Boolean
  Dim posMax As Long
  Dim posMin As Long
  If (UBound(s) - LBound(s) <= 1) Then Exit Function
  For idx1 = UBound(s) To LBound(s) + 1 Step -1
    posMax = LBound(s)
    posMin = UBound(s)
    looping = False
    For idx2 = idx1 To LBound(s) + 1 Step -1
      idx3 = idx2 - 1
      If _
        ((IsNull(s(idx2).keys) Or Empty = s(idx2).keys) And (Not IsNull(s(idx3).keys) And Empty <> s(idx3).keys)) _
      Or _
        (s(idx2).keys < s(idx3).keys) _
      Then
        ' 大きくなくちゃいけないのがNULLかEMPTYのとき
        ' 入れ替える
        t = s(idx2)
        s(idx2) = s(idx3)
        s(idx3) = t
        looping = True
        If (posMin > idx2) Then posMin = idx2
        If (posMax < idx2) Then posMax = idx2
      End If
    Next
    If looping = False Then Exit For
  Next
End Function

Public Function 配列値取得(s() As 配列要素, key As Variant) As Variant
  Dim cnt As Long
  Dim pos As Long
  Dim posMax As Long
  Dim posMin As Long
  Dim posMid As Long
  posMin = LBound(s)
  posMax = UBound(s)
  posMax = UBound(s)
  posMin = LBound(s)
  Do While (posMax - posMin > 3)
    posMid = (posMin + posMax) / 2
    If (s(posMid).keys < key) Then
      posMin = posMid
    Else
      posMax = posMid
    End If
  Loop
  For posMid = posMin To posMax
    If s(posMid).keys = key Then
      配列値取得 = s(posMid).values
      Exit Function
    End If
  Next
End Function

Public Function 配列値最大値(s() As 配列要素)
  Dim x As Long
  Dim v As Variant
  For x = LBound(s) To UBound(s)
    If (s(x).index > 0) Then
      If Empty = v Then
        v = s(x).values
      Else
        If v < s(x).values Then v = s(x).values
      End If
    End If
  Next
  配列値最大値 = v
End Function

Public Function 配列値最小値(s() As 配列要素)
  Dim x As Long
  Dim v As Variant
  For x = LBound(s) To UBound(s)
    If (s(x).index > 0) Then
      If Empty = v Then
        v = s(x).values
      Else
        If v > s(x).values Then v = s(x).values
      End If
    End If
  Next
  配列値最小値 = v
End Function

Public Function シートマージ()
  Dim srcキー列() As 配列要素
  Dim dstキー列() As 配列要素
  Dim srcインデックス行() As 配列要素
  Dim dstインデックス行() As 配列要素
  Dim srcSheets As String
  Dim dstSheets As String
  Dim x1 As Long
  Dim y1 As Long
  Dim x2 As Long
  Dim y2 As Long
  Dim s1 As String
  Dim s2 As String
  Dim x As Long
  Dim y As Long
  Dim キー項目 As String
  Dim addX As Long
  Dim addY As Long
  キー項目 = "名称"
  srcSheets = "Sheet1"
  dstSheets = "Sheet2"
  srcキー列 = 配列作成()
  dstキー列 = 配列作成()
  srcインデックス行 = 配列作成()
  dstインデックス行 = 配列作成()
  x1 = 1
  s1 = Sheets(srcSheets).Cells(1, x1)
  Do While s1 <> ""
    Call 配列値設定(srcインデックス行, s1, x1)
    x1 = x1 + 1
    s1 = Sheets(srcSheets).Cells(1, x1)
  Loop
  x1 = 1
  s2 = Sheets(srcSheets).Cells(1, x1)
  Do While s2 <> ""
    Call 配列値設定(dstインデックス行, s2, x1)
    x1 = x1 + 1
    s2 = Sheets(srcSheets).Cells(1, x1)
  Loop
  y1 = 2
  x1 = 配列値取得(srcインデックス行, キー項目)
  x2 = 配列値取得(dstインデックス行, キー項目)
  s1 = Sheets(srcSheets).Cells(y1, x1)
  s2 = Sheets(dstSheets).Cells(y1, x2)
  Do While (s1 <> "") Or (s2 <> "")
    If (s1 <> "") Then Call 配列値設定(srcキー列, s1, y1)
    If (s2 <> "") Then Call 配列値設定(dstキー列, s2, y1)
    y1 = y1 + 1
    s1 = Sheets(srcSheets).Cells(y1, x1)
    s2 = Sheets(dstSheets).Cells(y1, x2)
    DoEvents
  Loop
  'インデックス行のすり合わせ
  For x = LBound(srcインデックス行) To UBound(srcインデックス行)
    If (Empty = 配列値取得(dstインデックス行, srcインデックス行(x).keys)) Then
      ' ここにインデックス追加処理
      If Not Empty = 配列値最大値(dstインデックス行) Then
        addX = 1 + 配列値最大値(dstインデックス行)
        Call 配列値設定(dstインデックス行, srcインデックス行(x).keys, addX)
        Sheets(dstSheets).Cells(1, addX) = srcインデックス行(x).keys
      End If
      Debug.Print ""
    End If
  Next
  For y = LBound(srcキー列) To UBound(srcキー列)
    If Not IsNull(srcキー列(y).keys) And Empty <> srcキー列(y).keys Then
      If (Empty = 配列値取得(dstキー列, srcキー列(y).keys)) Then
        'ここにキー追加処理
        If Not Empty = 配列値最大値(dstキー列) Then
          addY = 配列値最大値(dstキー列) + 1
        Else
          addY = 1
          Do While Sheets(dstSheets).Cells(addY, 1) <> ""
            addY = addY + 1
          Loop
        End If
        Call 配列値設定(dstキー列, srcキー列(y).keys, addY)
        Sheets(dstSheets).Cells(addY, 1) = srcキー列(y).keys
        Debug.Print ""
      End If
      For x = LBound(srcインデックス行) To UBound(srcインデックス行)
        DoEvents
        If Not IsNull(srcインデックス行(x).keys) And Empty <> srcインデックス行(x).keys Then
          s1 = Sheets(srcSheets).Cells(srcキー列(y).values, srcインデックス行(x).values)
          If s1 <> キー項目 And s1 <> "" Then
            x2 = 配列値取得(dstインデックス行, srcインデックス行(x).keys)
            y2 = 配列値取得(dstキー列, srcキー列(y).keys)
            If Sheets(dstSheets).Cells(y2, x2) <> s1 Then
              Sheets(dstSheets).Select
              Sheets(dstSheets).Cells(y2, x2).Select
              Sheets(dstSheets).Cells(y2, x2).Font.Color = RGB(255, 0, 0)
              Sheets(dstSheets).Cells(y2, x2) = s1
            End If
          End If
        End If
      Next
    End If
  Next
End Function
久々に「Blog更新するか」と思い立ってfc2のログイン画面まできて、IDとやたらめんどくさいパスワードを入力した。
先日、それまで使っていたセキュリティソフトのライセンスが切れたので新しいのに変えてみたのだけど、同時にフリーのレジストリクリーナーと言うのを入れてみた。
どちらにも「パソコンを高速化する」という機能があるのだけれど、それでブラウザ周りの履歴とキャッシュを消去したのが原因だろう、全てのアカウントとパスワードが消えている。
他に思い当たるのないし。

無料のクラウドPCサービスに登録しているので、IDとパスワードなんかはそこにメモ書きを置いてあるのだけれど、そこへのパスワードも消えてて、意味不明な文字の羅列をいちいち入力するという羽目になった。
FC2でつかってるパスワードは10文字程度と長くはないのでソラでおぼえてるけど、妖しいのはたくさんあるし覚えるのを放棄したのもいくつかある。
自称でもプログラマーなので「パスワード生成プログラム」なるものを作ってあって、それで作ったランダムな文字列をパスワードに使っているので人間様には非常に覚えにくい。

最近は多段認証とかで「パスワード忘れた」となるとスマフォにワンタイムパスとか送るのが当たり前になってきているので「わかんね~!」となってもたいした手間なく復活できる。
しかしオジサンがネットワークを使い出した四半世紀も昔は、カスタマーサービスに電話して登録してある住所宛にワンタイムパス郵送してもらってそれが届くまでの1週間は旧パスワードでもログインできない、なんてのが当たり前だった。
牧歌的と言うか時間の流れがスローな時代だったねぇ。

セキュリティレベルが高くなればなるほどシステムは使いにくいものになる、というのは何もネットワークだけの話しではなくて、全てに言える。
玄関の鍵だってひとつよりふたつのほうが泥棒に入られにくいが、鍵の開け閉めの手間は2倍だ。
まぁ、プログラマーという人種は「楽をするために苦労することを厭わない」変なところがあるので複数のIDとパスワードを一元管理するツールとかは普通に作るものだ。
紙に書いたり、プログラム作ったりは人それぞれだけど。
先のパスワード生成するプログラムだって「同じパスワードだと不正利用が~」というので急遽こしらえたものだったりする。
自分でパスワード考えるの、面倒だから。

オジサンみたいに旧いタイプのプログラマなパソコンユーザーだと、実の処セキュリティの関心は高くないのが多々居る。
相当昔の話になるけど、プログラマーとオペレータとでは「自分が不正アクセスできるスキルをもっているか?」という質問に対して、オペレータは「ある」という人が多かったがプログラマーは「ない」が多かったというアンケートの結果を、見た覚えがある。
そもそも関心が無いのでスキルが身につかない、というところまでそのアンケートは分析していた。
しかし実情は、ケッコウ違うとオジサンは自分の例を元に考えている。

『プログラマーは楽するために苦労を厭わない』といったけど、これはもともとは『エンジニアは』という言い回しだったはず。
最初に目にしたのは1978か79年、そのくらいの頃に技術系の雑誌だったかニュース誌だったと思う。
それから20余年たって『プログラマーは』という言い回しにデジャブを覚えたものだ。
以来、たびたび口にしてるのでひょっとしたらおじさんのオリジナルと思ってる人も世の中にはいるかもしれない。

エンジニア、つまり技術系の人間は『必要な苦労は厭わない』がそれはあくまでも『楽をするため』なので『苦労する必要を認めない』ことに労力をかけたくないという、ずぼら人間でもある証拠だったりする。
身だしなみが「だらしない」とか「不潔」とかそういう目で見られがちだが、それはあくまでも結果。
根底には「ジーパンとスラックスと何が違うの?」という「服は服でしょ?」という、全てにおいて独自の価値観で、それに基づいて合理的にカテゴライズする思考がある。

オジサン的には「食器洗い」がもうちょい効率的にならないかと考えている。
引越しして職場環境が変わって生活習慣も変わって、3度の食事を自分で作るようになったから余計にそう思う。
食器洗い洗剤で洗い、流水で流し、籠において水を切って、乾いたら食器棚へ移す。
この「乾いたら」が意外に面倒。
一人で使う食器などタカが知れている。
ご飯茶碗に、汁者の椀に、皿が1枚かせいぜい2枚。
ピラフとかにした時には皿1枚だけとかも。
そこでやりだしたのが、ウェットティッシュを使う方法。
流水で洗剤をながしたらウェットティッシュで拭いてそのまま食器棚に入れてしまう。
使い捨て布巾のノリで拭いてしまうのだ。
それにアルコールは水より揮発性が高く、また気化するときに水を道連れにしていく特性がある。
大して差はないとはいえ布巾で拭いただけのときよりも乾燥する時間は気持ち短いし、なにより洗い残した油汚れがウェットティッシュで拭くと意外に落ちるのだ。
殺菌も確実行われるので男やもめには良い方法だと自負している。

それを知人に話したら「なにそれ」と呆れられたが、手を抜くことは悪いことじゃないはずだ。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。