パスワードを忘れた? アカウント作成
65672 journal

hoagの日記: 僕らはだれと競争しているのだろう

日記 by hoag

おごちゃんの雑文 技術者の給与が相対的に安いらしいが… と、その前段のエントリである プログラミングに誇りを持ちたいなら単価を考えないこと を読んで考えた。

まず、考えた事は、やられたなぁって事。そのうちどこかに書こうと思っていた 事が、大体書かれてしまっている。簡単に言うと、給料の多寡は何によって決まるの だろうっていう、素朴な疑問。結論から言うと、取り替えの利かない事。 あるいは利きにくい事、となる。

おごちゃんさんは「かけがえのない仕事をしている」って言い方をしている。 IT 技術者についての話なので、「外から買って来れない技術を持っている」かどうか、と。 一般的な職業に置き換えれば、医者とか弁護士とかに該当する。 つまり、高度な専門性とか教育の必要性って事だ。

さらに、こちらの記事も同様。これから書こうと思っていたのに。 ウェブ開発ブームの終焉。 かつてプログラマには、それだけで特殊性や専門性があった。 でも、今はプログラマ自体もコモデティ化し、取替え可能になってしまった。

確か、 EARLY MORLEY BIRD でモーリーが言ってた事。開放政策が何をもたらしたか。

経営者にとってのコストという観点で考えてみる。

僕らの給料ってのは、つまり、経営者にとっては生産コストだ。 当然それは安い方が良い。かつては、その選択肢は国内に限られていた。

でも、ある時期から、国外に工場を作ったりして生産拠点を移すって事が 多くなった。IT 業界ではオフショア開発とか言ってたヤツだ。 つまり、同じものを自国で作るか、外国でつくるかの選択が行われた結果、 外国を選んだって事だ。これはそのまま、労働者として自国の人間を 選ぶか、外国の人間を選ぶかって事と重なる。

つまり、僕ら労働者は今や、中国やインド等、世界中の労働者と競争しているのである。 いや、させられているのである。

そして、コモデティ化し、取替え可能な労働力としての僕らは、生活の為に 目の前の仕事を得ようとするなら、自分を安売りするしかないのである。

全世界を競争の場とした、主に労働力を対象にしたコスト引き下げ努力の結果、 モノの値段は下がった。 今までは、そのメリットを享受できた。でも、これからは、このフラットな 競争の方が効いてくるかもしれない。

まぁ、そんな単純なシナリオではないと言われるだろうし、それは正しいと 思う。ただ、長期的な傾向としては、外れていないはず。もし、このまま行けば。

以下、余談。

「アメリカでの技術者の待遇が良いのはどう説明するのだ」 に対する別の説明。と、言っても、とある漫画の受け売り。

アメリカでは、職に人をアサインする。日本では会社の構成員に人をアサインし、 その社員に仕事を割り当てる(この構造もだいぶ崩れているのは、先の派遣切りの時の 社員切りで明確になった)。 例えば、アメリカではそのポジションが不要になったら、その人は失業する事になる。 でも、日本ではその場合、どこかから仕事を見つけてきて、その人に与える。 つまり、セーフティネットの分が違うのだ。

アメリカ式は、全てがフリーランスか契約社員みたいなものなのだ。 フリーなら、保障が無い分、収入が高いのは当然となる。

65362 journal

hoagの日記: ディレイ オブ 天気 3

日記 by hoag

あるとき、ふと、考えた。冬至の日って別に寒くないよなぁ。寒いのはずっと 先。月単位で先になるよなぁ。

つらつら考えるに、地球(ちたま)が暖まったり冷えたりするのは、もちろん太陽光に よる熱に由来するんだが、気温は、その累積された効果として観察される事になる、 と云う事なのだな。

だから、気温の最大/最小の時期は、照射量の最大/最小の時期から遅れる事になる。 で、そのディレイの量が、どうやら温まる方向も冷える方も一緒で、二ヶ月位である、と。

1 年の中で最も寒い時期は冬至の二ヶ月後の 2 月中旬。 暑い方は夏至の二ヶ月後の 8 月中旬。そういう事。

いや、ちょっと不思議だったんだ。北欧辺りの説明として、冬至の日が冬から春に向かう 折り返しの日として祭りを行う町が多々あるって話。12 月なんて、まだ冬の 入り口で、スキー場なんかだと、やっと営業を開始したばっかりだったりするし。 なんか、共感できないって言うか。

振り返ってみると、日本で生活していて、冬至とか夏至とかってあまり意識しない 気がする。と言うか、全然、体感にならない。

この差は何? 緯度の差?

多分そうなんだろう。つまり、日照時間はまぁまぁ有るから、フォーカスは寒さに向かう、 と。

ちなみに、寒さの最盛期が 2 月ってのも、英語の教科書に載っていた例文で初めて 意識した事だったりする。

インドア派はこれだよ。

65144 journal

hoagの日記: えぬてーぴー 1

日記 by hoag

NTP に NICTを追加してみた。

最初、設定で手間取ったのは、他の記述と同様に書いて、繋がらなかった所。 結局、-4 オプションが必要って分かって、以下の記述となった。

server -4 ntp.nict.jp iburst minpoll 6 maxpoll 16

Q&Aポーリング間隔(アクセス回数)に制限はありますか? に「"maxpoll N" の "N" を "8" 以上(256秒間隔以上)に設定してください」 とあるので、まあ、倍位ならどうかな、と16 にしてみた。ntpq -p で見てみると poll が 68m となっている。ちょっと長すぎ? これって 2 の累乗?
そうかぁ。
無指定で 1024 と、256 秒より長いのだから、それで良いかもしれない。と、 言うか、負荷を嫌うのなら、minpoll の指定の方が重要な気もする。 と、ここで気づいた。最初は 64 から始めるのだから、minpoll 6 maxpoll 10 が デフォルトじゃん。まぁ、意識させるために、敢えて項目を立てているのかも しれないなぁ。

で、-4 が明示的に必要って事は、何が違うのだろうと思ったら、どうも DNS で AAAA レコードが引けるかどうかが違う模様。
他分 ntpd は、 DNS でまず AAAA を引いて、見つかったら、その宛て先に通信を 試みるのだろう。で、それに失敗しても改めて A レコードを引きなおす事はしない 、と。

今後、ntpd が参照しているサーバの AAAA レコードが新規に登録されると、 上記の様に IPv6 で接続に行って、結果、急に同期が取れなくなる、なんて事態 があるかもしれないなぁ。

ntpq -p で見てみると、stratum 1 のせいだろう。delay や jitter にかかわらず NICT を同期対象に選んでいる様に見える。 インターネットマルチフィードRing Server Projectと 併用していると、こちらは殆どが stratum 2 のためか選択されていない。 確かに jitter は NICT が一番良い値なのだが。でも、delay や offset は大きいしなぁ。

結局、NICT は外す事にした。

元々、 Wikipedia を読んで NICT を見つけたことで始めた事なのだが、ここにもちょっと引っ掛かりが。
昔、どこかで、 NTP は、回線の上りと下りの速度が同じという前提があるって話を 読んで、ずっと気になっていたのだが、そういう記述が Wikipedia には見当たらない。
Wikipedia では、「通信遅延時間の計測」の項で「往復の通信時間を計測することで~」 と、上りと下りの遅延を合わせて扱う様に書いてある。で、「執筆中」と。

今は上りと下りの速度が違う方がフツーだと思うのだが、そもそも NTP は現状に 合ってないって事なのだろうか。それともイマドキの ntpd なら対策されているのだろうか。

64244 journal

hoagの日記: シネマの風景

日記 by hoag

とある漫画家の人のブログでみつけた シネマの風景

まぁ、映画のロケ地紹介であり、観光にいらっしゃいな本だとおもう。

が、勝川さんのファンだし、北海道も好きなので、貼ってみるかな、と。

61246 journal

hoagの日記: 1

日記 by hoag

ここ 2 ~ 3 年の傾向なのだが、助詞が「が」に収束して行ってる様に見える。 で、その事例がまた一つ。

Debian GNU/Linux 5.0 がリリース という、うれしいニュース。

僕の感覚では、「lenny をリリース」とか「lenny がリリースされる」となる 方がしっくりくる。

web でニュースサイトを見ていると、割と出会うし、最近は紙媒体の新聞でも 見た記憶がある。

この感覚に一番影響しているのは、当然、小学校時代に受けた国語教育のはずだが、 イマドキはどう教えられているのだろう。例によってゆとり教育のせいって事に なるのだろうか。

一度、スラッシュ国民投票辺りで調べてほしいものだな。この表現に違和感を 持ちますか?って感じで。

57557 journal

hoagの日記: vbs で pdumpfs もどきを作ってみた

日記 by hoag

まぁ、目的は自分で使うため。

一応、vbs と wsf に分かれている。こうしておくと複数の対象に対して使う場合に 便利。vbs をライブラリ的に使い、wsf を必要なだけコピーして、パラメータを 適宜修正して使う事ができる。また、vbs が 1 つだけなので、修正が発生しても 変更するファイルが 1 つで済む。
使う時には、vbs と wsf を同じディレクトリに置く。

なお、fsutil コマンドが一般ユーザで使えないので、 vbs を管理者権限で起動させる vbs もつけた。 右クリックから「管理者として実行」も選択できるが、 いつもだとそれも面倒だから。

元と異なる点も幾つか。
バックアップディレクトリを日付だけでなく日付+時刻にするモード。 その他、幾つかの動作モード。

注意点も幾つか。ファイルの比較で、サイズと修正時刻しか見ていない。つまり、中身を 読んでいない。さらには、前回保存したディレクトリの同名のファイルしかチェック していない。内容の比較とか、バックアップ全体の中での同一ファイルのサーチ とかは todo 。
また、スクリプトは UTF-8 で保存する必要がある。あるいは wsf の先頭行での 宣言を修正する。
まぁ、日本語のコメントを全部潰すでも OK だな。または wsf の記述を vbs に移して 1 ファイルにするとか。

以下、ファイル名と内容

libBkup.vbs

Option Explicit
'
' -- target: set in each wsf ------------------------------------------
'
'Const BK_SRC = "d:\work"
'Const BK_DST = "C:\Documents and Settings\user\My Documents\work\backup"

'
' -- param: set in each wsf -------------------------------------------
'
'Const  NO_EXEC = False                 ' True | False
'Const  MODE_PDUMPFS = True             ' True | False
'Const  SKIP_HIDDEN = True              ' True | False
'Const  SKIP_SYSTEM = True              ' True | False
'Const  SKIP_COPY_ERROR = False         ' True | False
'Const  SKIP_LARGE_SIZE = "1G"          ' 0 | "1.2G" | bytes
Dim SkipBySize, SKIP_BY_NAME, SKIP_BY_EXP
'SKIP_BY_NAME = Array( _
'                   "a", "b", "c" _
'               )
'SKIP_BY_EXP = Array( _
'                   "*.bak", "*.o", "ABC??.tmp" _
'               )

'
' -- const ------------------------------------------------------------
'
Const   Hidden = 2      ' 隠しファイル
Const   System = 4      ' システム ファイル
Const   COMMAND_MAKE_LINK = "fsutil hardlink create"    ' ハードリンク作成コマンド

'
' -- procedures -------------------------------------------------------
'

' is target ?
Function    isTarget( src, file )
    Dim fso, f, s, re, p, ret

    ret = True

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    Set f = fso.GetFile( fso.BuildPath( src, file ) )

    If SKIP_HIDDEN And (0 <> (f.Attributes And Hidden)) Then
        ret = False
    ElseIf SKIP_SYSTEM And (0 <> (f.Attributes And System)) Then
        ret = False
    ElseIf (0 <> SkipBySize) And (SkipBySize < f.Size) Then
        ret = False
    End If

    If ret Then
        For Each s In SKIP_BY_NAME
            If s = f.Name Then
                ret = False
                Exit For
            End If
        Next
    End If

    If ret Then
        Set re = New RegExp
        re.IgnoreCase = True
        re.Global = True
        For Each s In SKIP_BY_EXP
            p = 1
            Do
                p = Instr( p, s, "?" )
                If 0 = p Then
                    Exit Do
                End If
                s = Left( s, p - 1 ) & "." & Mid( s, p + 1 )
                p = p + 1
            Loop
            p = 1
            Do
                p = Instr( p, s, "*" )
                If 0 = p Then
                    Exit Do
                End If
                s = Left( s, p - 1 ) & "." & Mid( s, p )
                p = p + 2
            Loop
            s = s & "$"
            re.Pattern = s
            If re.Test( f.Name ) Then
                ret = False
                Exit For
            End If
        Next
        Set re = Nothing
    End If

    '
    ' todo: any check
    ' time regexp or else
    '

    Set f = Nothing
    Set fso = Nothing

    isTarget = ret
End Function

' check if same
Function    isSameFile( src, dst, file )
    Dim fso, sf, df, s, d, ret

    If NO_EXEC Then
        isSameFile = False
        Exit Function
    End If

    ret = True

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    sf = fso.BuildPath( src, file )
    df = fso.BuildPath( dst, file )
    If Not fso.FileExists( df ) Then
        ret = False
    Else
        Set s = fso.GetFile( sf )
        Set d = fso.GetFile( df )
        If s.Size <> d.Size Then
            ret = False
        ElseIf s.DateLastModified <> d.DateLastModified Then
            ret = False
        End If
        Set d = Nothing
        Set s = Nothing
    End If

    '
    ' todo: any check
    ' hash(md5/sha1) or else

    Set fso = Nothing

    isSameFile = ret
End Function
' search in dst directory
Function    searchSamefile( src, file, top )
    ' todo: search in 'top' directory
    ' return: fullname if found, or Empty
    searchSamefile = Empty
End Function

' log: todo: write to logfile or else
Sub log( msg )
    WScript.Echo( msg )
End Sub

' date/time
Function    getYear
    getYear = Right( "" & Year( Now ), 4 )
End Function
Function    getMonthr
    getMonthr = Right( "0" & Month( Now ), 2 )
End Function
Function    getDay
    getDay = Right( "0" & Day( Now ), 2 )
End Function
Function    getHour
    getHour = Right( "0" & Hour( Now ), 2 )
End Function
Function    getMinute
    getMinute = Right( "0" & Minute( Now ), 2 )
End Function

' directory/file name
Function    quotePath( path )
    If 0 < InStr( path, " " ) Then
        quotePath = """" & path & """"
    Else
        quotePath = path
    End If
End Function
Function    getDstDir( dst )
    Dim fso, s

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    s = fso.BuildPath( dst, getYear )
    s = fso.BuildPath( s, getMonthr )
    s = fso.BuildPath( s, getDay )
    If Not MODE_PDUMPFS Then
        s = fso.BuildPath( s, getHour )
        s = fso.BuildPath( s, getMinute )
    End If
    Set fso = Nothing

    getDstDir = s
End Function

'
Function    searchLastDir( dst, level )
    Dim fso, folders, folder, d
    Dim max, maxname, i
    Const   MAX_TAG = Empty

    max = MAX_TAG
    Set fso = CreateObject( "Scripting.FileSystemObject" )
    Set folder = fso.GetFolder( dst )
    Set folders = folder.SubFolders
    For Each d In folders
        If IsNumeric( d.Name ) Then
            i = 1 + CInt( d.Name )              ' 0 < Empty < 1
            If max < i Then
                max = i
                maxname = d.Name
            End If
        End If
    Next
    Set folders = Nothing

    If MAX_TAG = max Then
        searchLastDir = Empty
        Set fso = Nothing
        Exit Function
    End If

    d = fso.BuildPath( dst, maxname )
    Set fso = Nothing

    If 0 = level Then
        searchLastDir = d
    Else
        searchLastDir = searchLastDir( d, level - 1 )
    End If
End Function
Function    getLastDir( dst )
    Dim level

    If Not MODE_PDUMPFS Then
        level = 4
    Else
        level = 2
    End If
    getLastDir = searchLastDir( dst, level )
End Function
' check existing file/directory
Function    isExist( file )
    Dim fso

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    If fso.FileExists( file ) Then
        isExist = True
    ElseIf fso.FolderExists( file ) Then
        isExist = True
    Else
        isExist = False
    End If
    Set fso = Nothing
End Function
' make directory
Function    mkdir( dir )
    Dim fso

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    On Error Resume Next
    fso.CreateFolder( dir )
    mkdir = (0 = Err.Number)
    On Error Goto 0
    Set fso = Nothing
End Function
Function    createParentsDir( dir )
    Dim fso, path, names, i

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    names = Split( fso.GetAbsolutePathName( dir ) , "\" )
    path = names( LBound( names ) ) & "\"
    For i = (LBound( names ) + 1) To UBound( names )
        path = fso.BuildPath( path, names( i ) )
        If Not isExist( path ) Then
            If Not mkdir( path ) Then
                log( "ERR: make directory: " & path )
                createParentsDir = False
                Set fso = Nothing
                Exit Function
            End If
        End If
    Next
    Set fso = Nothing
    createParentsDir = True
End Function
' file/path name
Function    getPath( fullname )
    Dim fso

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    getPath = fso.GetParentFolderName( fullname )
    Set fso = Nothing
End Function
Function    getFile( fullname )
    Dim fso

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    getFile = fso.GetFileName( fullname )
    Set fso = Nothing
End Function

' copy or link
Function    copyFile( src, dst, file )
    Dim fso, s, d

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    s = fso.BuildPath( src, file )
    d = fso.BuildPath( dst, file )
    If NO_EXEC Then
        copyFile = True
        log( "TEST: copy: " & s & vbCrLf & "  --> " & d )
    Else
        On Error Resume Next
        fso.CopyFile s, d
        copyFile = (0 = Err.Number)
        On Error Goto 0
    End If
    Set fso = Nothing
End Function
Function    makeLink( sf, df )
    Dim fso, wso, cmd, ret

    If NO_EXEC Then
        log( "TEST: link: " & sf & vbCrLf & "  --> " & df )
        Exit Function
    End If

    cmd = COMMAND_MAKE_LINK & " " & quotePath( df ) & " " & quotePath( sf )
    Set wso = WScript.CreateObject( "WScript.Shell" )
    ret = wso.Run( cmd, 0, True )
    Set wso = Nothing

    makeLink = (0 = ret)
End Function
Function    linkFile( src, dst, file )
    Dim fso, s, d

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    s = fso.BuildPath( src, file )
    d = fso.BuildPath( dst, file )
    Set fso = Nothing

    linkFile = makeLink( s, d )
End Function
Function    backupFile( src, dst, last, top, file )
    Dim fso, f, d

    If isTarget( src, file ) Then
        If Empty = last Then
            backupFile = copyFile( src, dst, file )
        Else
            If isSameFile( src, last, file ) Then
                backupFile = linkFile( last, dst, file )
            Else
                f = searchSamefile( src, file, top )
                If Empty = f Then
                    backupFile = copyFile( src, dst, file )
                Else
                    Set fso = CreateObject( "Scripting.FileSystemObject" )
                    d = fso.BuildPath( dst, file )
                    Set fso = Nothing
                    backupFile = makeLink( f, d )
                End If
            End If
        End If
    Else
        backupFile = True
    End If
End Function
Function    backupDir( src, dst, last, top )
    Dim fso, folder, files, folders
    Dim f,d, sd, dd, ld, ret

    ret = True

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    Set folder = fso.GetFolder( src )

    Set files = folder.Files
    For Each f In files
        ret = backupFile( src, dst, last, top, f.Name )
        If Not ret Then
            log( "ERR: backup file : " & src & " / " & f.Name )
            If Not SKIP_COPY_ERROR Then
                Exit For
            End If
        End If
    Next
    Set files = Nothing

    If (Not SKIP_COPY_ERROR) And (Not ret) Then
        log( "ERR: backup file" )
        backupDir = ret
        Set folder = Nothing
        Set fso = Nothing
        Exit Function
    End If

    Set folders = folder.SubFolders
    For Each d In folders
        If ((Not SKIP_HIDDEN) Or (0 = (d.Attributes And Hidden))) _
        And ((Not SKIP_SYSTEM) Or (0 = (d.Attributes And System))) Then
            sd = fso.BuildPath( src, d.Name )
            dd = fso.BuildPath( dst, d.Name )
            If (Not NO_EXEC) And (Not mkdir( dd )) Then
                log( "ERR: make directory: " & dd )
                ret = False
                Exit For
            End If
            If Empty = last Then
                ld = Empty
            Else
                ld = fso.BuildPath( last, d.Name )
            End If
            ret = backupDir( sd, dd, ld, top )
            If Not ret Then
                log( "ERR: backup directory: " & sd )
                If Not SKIP_COPY_ERROR Then
                    Exit For
                End If
            End If
        End If
    Next
    Set folders = Nothing

    Set folder = Nothing
    Set fso = Nothing

    backupDir = ret
End Function
'
Function    backup( src, dst, last )
    Dim fso, f

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    f = fso.FileExists( src )
    Set fso = Nothing

    If f Then
        backup = backupFile( getPath( src ), dst, last, dst, getFile( src ) )
    Else
        backup = backupDir( src, dst, last, dst )
    End If
End Function

'
Function    checkArg
    Dim f, m

    ' SKIP_LARGE_SIZE --> SkipBySize
    If Not IsNumeric( SKIP_LARGE_SIZE ) Then
        m = Right( SKIP_LARGE_SIZE, 1 )

        On Error Resume Next
        f = CDbl( Left( SKIP_LARGE_SIZE, Len( SKIP_LARGE_SIZE ) - 1 ) )
        If 0 <> Err.Number Then
            f = Empty
        End If
        On Error Goto 0
        If Empty = f Then
            checkArg = False
            Exit Function
        End If

        Select Case UCase( m )
        Case "K"    SkipBySize = f * 1000
        Case "M"    SkipBySize = f * 1000 * 1000
        Case "G"    SkipBySize = f * 1000 * 1000 * 1000
        Case "T"    SkipBySize = f * 1000 * 1000 * 1000 * 1000
        Case Else   checkArg = False: Exit Function
        End Select
    Else
        SkipBySize = SKIP_LARGE_SIZE
    End If

    checkArg = True
End Function

'
' -- main -------------------------------------------------------------
'
Sub main()
    Dim fso, src, dst
    Dim this, last

    If Not checkArg Then
        log( "ERR: check Argumets: " )
        Exit Sub
    End If

    Set fso = CreateObject( "Scripting.FileSystemObject" )
    src = fso.GetAbsolutePathName( BK_SRC )
    dst = fso.GetAbsolutePathName( BK_DST )
    Set fso = Nothing

    If Not isExist( src ) Then
        log( "ERR: source not found: " & src )
        Exit Sub
    End If

    If Not isExist( dst ) Then
        If Not NO_EXEC Then
            log( "WARN: destination not found: " & dst )
            If Not mkdir( dst ) Then
                log( "ERR: make directory: " & dst )
                Exit Sub
            End If
        End If
    End If

    last = getLastDir( dst )
    this = getDstDir( dst )
    If isExist( this ) Then
        log( "ERR: write directory is exist. Prev work not finished ?" )
        Exit Sub
    End If
    If Not NO_EXEC Then
        If Not createParentsDir( this ) Then
            log( "ERR: create directorys: " & this )
            Exit Sub
        End If
    End If

    If Not backup( src, this, last ) Then
        log( "error" )
        Exit Sub
    End If

    WScript.Echo( "done" )
End Sub

bkup.wsf

<?XML version="1.0" encoding="utf-8" standalone="yes" ?>
<!-- Backup Like pdumpfs  -->
<package>
    <job id="Backup">
        <?job error="True" debug="True" ?>
        <script language="VBScript" src="libBkup.vbs"/>
        <script language="VBScript">
        <![CDATA[
            ' バックアップ
            Option Explicit
            '
            ' -- target -----------------------------------------------
            '
            Const BK_SRC = "C:\Documents and Settings\user\My Documents\work"
            Const BK_DST = "d:\backup"
            '
            ' -- mode -------------------------------------------------
            '
            Const   NO_EXEC = False                 ' True | False
            Const   MODE_PDUMPFS = True             ' True | False
            Const   SKIP_HIDDEN = True              ' True | False
            Const   SKIP_SYSTEM = True              ' True | False
            Const   SKIP_COPY_ERROR = False         ' True | False
            Const   SKIP_LARGE_SIZE = 0             ' 0 | "1.2G" | bytes
            SKIP_BY_NAME = Array()                  ' "filename1", "filename2"
            SKIP_BY_EXP = Array()                   ' "*.bak", "exp??.tmp"
            '
            ' -- start ------------------------------------------------
            '
            main
        ]]>
        </script>
    </job>
</package>

runas.vbs

Option Explicit
Const   VBS = "C:\Documents and Settings\user\My Documents\bkup\bkup.wsf"
Sub main()
    Dim sao, cmd
    cmd = """" & VBS & """"
    Set sao = CreateObject( "Shell.Application" )
    sao.ShellExecute "wscript.exe", cmd, "", "runas"
    Set sao = Nothing
End Sub
main

54571 journal

hoagの日記: pdumpfs が Windows でドライブのトップディレクトリをうまく扱えないのは Vist64 固有

日記 by hoag
一寸、調査してみた。 結果、find モジュールの不具合であって、pdumpfs のせいでは無い模様。 しかも、不具合と言うより、Vist64 非対応という事になる模様。

前回、pdumpfs を動かしてみた所、 ドライブの最上位ディレクトリを指定した場合にうまく動かなかった事を書いた。 その後、Vista64 だからなのかも、と思い、XP(SP3 32 bit の別 PC) で試してみたところ、 ちゃんと動いてしまった。

なので、pdumpfs のソースと ruby の win 用バイナリを取ってきて、調べてみた。

pdumpfs でうまく動いていない箇所は recursive_copy 関数の以下の部分

      Find.find(src) do |s|
        ・・・
      end

ここで取得されるべきファイルの一覧がおかしい。スクリプトを起動した( 当然、指定とは別のドライブにある)ディレクトリの配下が、なぜか取得されたりする。 バージョンによっては何も取れない事もある様だが、むしろこちらの方が自然な異常動作 (なんやそれ)な感じがするのだが。まぁ、自然な異常など無いって事で。

例えば、コマンドラインで "D:\" と指定すると、処理の流れは以下の様になる

  1. start 関数に src 引数として渡される
  2. start 関数の以下の処理で "D:/" と変形される

          if windows?
            src  = expand_special_folders(src)
            dest = expand_special_folders(dest)
          end

  3. start 関数の以下の処理で "D:" と変形される。末尾の '/' が除かれる。

          src  = src.sub(%r!/+$!, "") unless src == '/' #'

  4. 初回なので、start 関数から recursive_copy 関数が呼び出される
  5. recursive_copy 関数で Find.find(src) do |s| のループを実行し空振りする

対策は find モジュールで対応となるべき。ただ、そこまでは追いかけていない。 で、ここではアドホックな解を。 'D:' の様な場合を 'D:/' とする事で回避できるので、

      if windows?
        src = src.sub( /^[A-Za-z]:$/, src + "/" )
      end

な、感じのコードを find() の前に入れる、でどうだろうか。 ruby は初心者なので、もっと短くできると思われるが。

テストは mswin32版の安定版・開発版 の先の Release ページからだと ftp でしか取れない様なので、 Ring Server から、 32 bit 版64 bit 版 最新版を Release ページ のファイル名で探して、 取得した。

そうそう、テストコードは以下

require 'find'
Find.find( "D:" ) do |s|
    print "Find: ", s, "\n"
end

D: ドライブがある環境が必要なので unit 化とかできないけど。

それにしても、find() だけでディレクトリの中まで入って全てリストアップ してくれるんだから、このモジュールは結構優れもの。

ちなみに ':' は unix 環境では通常は出現しなかったはず。 出現するのは、例えば NFS で ホストを指定する場合等だったはず。では、pdumpfs がそこまで考慮すべきかというと、 どうだろう。
個人的意見としては、アプリはそこまで考慮しなくて良い。あるいは、してはいけない、 となる。unix の「単一のファイルツリー」モデルのままにしておく事こそが、 強力な武器になる。そう思うので。
まぁ、mount すればいいじゃん、とも言う。
あるいは ftp://~ とか http://~ の様な URI を fs の層でなんとかするとか。

453271 journal

hoagの日記: VBScript から NTFS のハードリンクが(標準では)作れないらしい

日記 by hoag

何かで見て、ふと使ってみようと思ったバックアップソフト、pdumpfs。 以前にも見た事があるはずだが、その時はスルーしていた。

ところが、うまく使えない。具体的には Windows 環境でドライブのトップディレクトリをソースとして指定すると、 うまくいかない。まぁ、元々 UNIX が出自なのであまり考慮が無いのは、そんなもんかなぁって感じでもあるが。

仕方ないので、ドライブを別のドライブの空ディレクトリにマウント(ジャンクションとかいうらしい)して実行してみたが、 こんどは途中でエラー終了。どうやら System Volume Information なんてディレクトリをコピーしようとして失敗したらしい。

まぁ、ソースも短いし、Win 特有の事情を考慮するコードを追加して回避するのもそんなに難しく無いと思う。ドライブのルートディレクトリが 指定されたときにどう見えるかを確認して特別扱いする。System Volume Information に関しては属性を調べて システム/隠しファイル属性をスルーする、辺りを入れれば多分、動くと思う。ただ、環境を作るのが面倒くさい。

で、VBScript で再実装できるかなぁ、と思って、予備調査してみたら、VBScript からは NTFS のハードリンクの作成が どうも出来ない様だった。正確には、ハードリンクを作成するための COM コンポーネントが用意されていない、と言う べきか。MSDN のサンプルコード は、あるのだが、別途 DLL が必要らしい(入手と登録)。また、そういう COM コンポーネントを作っている人 も居るのでそれを使えば可能は可能のはず。ただし、別途作成している人が居るって事は、標準では使えないって事でもある。 VBScript を使う意味として、標準で提供されている機能の中で実装するって事もあるので、取りあえず見送り。

また、Windows 付属のコマンド でやる手もある のだが、試してみた所、実行時に管理者権限を要求するので、これも見送り。なぜなら、pdumpfs は一般ユーザ権限で実行できているから。 まぁ、それ以上に、スクリプトからファイル 1 個ずつに対して外部コマンドを起動するのは効率が悪すぎだと思うし。

pdumpfs がどうやって実装しているかと言うと Win32 API を直接呼び出している。VBScript から、これが出来れば良いのだが、 この項を調査するところで力が尽きた。VB なら出来るのだが、VBS はどうなのだろう。

と、言う訳で、残念ながら出来なかった、と言うところまでで終了。(お、なんか日記っぽい)

何か、素直に pdumpfs を使う気になれないのは、名前のせいもある。単なるコマンドに fs って名前を付けるのはどうだろう。 但し、元の dumpfs がそうなっているので、pdumpfs に罪をかぶせる事は出来ない模様なのだが。

ただ、ポイントは、無変更のファイルをハードリンクで実現するって点なので、Plan9 とは切り離しても良いのではないかって気もする。

そういえば、一時期、バックアップの話題として、同一のファイルをまとめてしまうことでディスクの容量を節約するって話題があった。具体的には、 複数ユーザがメーリングリストのメールを個別に保存する様な場面を想定していて、ディスク上では別々に保存された ものの内容が同一の場合を検出して、その場合は 1 つにまとめてしまうってもの。同一かどうかのチェックにはハッシュを使う、と。 (もし、MD5 を使っていたら、今頃、 大変なのだろうなぁ) これに合わせ技として、この、内容が同一のファイルをハードリンクで保存ってのも使えると思う。個別に修正された場合の対処をどうしようとか、 そもそも修正させない様、リードオンオンリーにするべしとか、バックアップからの取り出しのインターフェイスを専用にするとか、 運用上の制限とかツールの実装とかをうまく決めてしまえば。

でも、pdumpfs のアイディアの一番の優れた点は、日付でファイルの一揃いの一覧が常に見渡せる点にあると思う。なぜなら、 ファイルの取り出しが、その、見えているファイルの、単なるコピーで良いっていう点こそが秀逸、って言うよりユーザフレンドリー なのだから。(日付っていう点も改善して欲しい点/再実装しようと思った動機の 1 つ。1 日の中で何回でも、 節目毎にバックアップを取りたいって欲求もあるのだから) 重複するファイルの実体をハードリンクで保存する事で、ディスク容量を節約する以上に。

たとえば、LFS のスナップショット機能などは同様の機能が提供できるわけだが、pdumpfs のアイディアでは取り出しに専用ツールが不要で、ユーザが操作しやすい(概念的にも理解しやすい)。 結果的に初心者に優しい点が大きなメリットなのだと思う。

453844 journal

hoagの日記: 手元 web サーバのススメ

日記 by hoag

昨日の日記で、手元で CGI を動かして、mp3 の再生とかさせて、快適って話を書いたのだが、 手元に web(cgi) サーバがあると、何かと使える。

特に重宝するのが、めも的にドキュメントを残したい場合。以前はどこかのページに感化されて Changelog 形式のテキストファイルに放り込む、なんて事もやっていたけど、今は wiki を動かしている。 使っているのは WiLiKi ってやつ。 Debian だと wiliki パッケージ。Gaucheで 動いているので、gauche パッケージが必要。
書式が wiki なので、生 html を書くよりはるかに簡単だし、装飾も付けられて、読むときも見やすくできる。 外部リンクも貼れるし、もちろん検索も出来る。

ちなみに i386 な環境から amd64 や ia64 な環境に .dbm ファイルをそのままもって行っても 動かないそうなので、 武藤さんが作ってくれたスクリプト を利用させてもらうと良いだろう。

その他だと、まとまった量の文書を書くのに、DocBook で書いて、html を生成して、それを web 経由で確認、なんて事もやっている。.xml で書いておくと、後で色々な形式に変換できるって 事で。まぁ、html 以外の生成はやってないけど。

また、技術文書などでは Gauche のリファレンスマニュアルの 様にまとめてダウンロードできるようにしてくれているサイトも多いので、これを手元に展開して見る時にも使える。

その他、常時動いている web(cgi) サーバがあるなら cron で定期的な作業をさせて、結果を web から 見られるようにするとか。常時は動いていなくとも、サーバ側で何かコマンド実行させるとか、色々と応用は利く。

と、言う訳で、冬休みの工作気分でどうよ、という事で。

453845 journal

hoagの日記: Linux でユーザをグループに参加させる方法 x3

日記 by hoag

時々必要になって検索するのだが、妙に引っ掛かりが悪いのが、この、 ユーザをグループに追加する方法。

その 1

# adduser USER GROUP

最もシンプルなので、これが好み

その 2

# groups USER
USER : USER news cdrom audio games
# usermod -G news,cdrom,audio,games,GROUP USER

※デフォルトグループ(ユーザ名と同名のグループ)は省略する
グループを列挙する必要があって、ちょっと面倒。 コンソールの様なコピペできない環境だと typo が心配だし。

その 3

# vi /etc/group

直接編集する。形式は以下

GROUP:x:29:USER,USER2

コマンドの詳細は OS 毎に微妙に異なる可能性が在るので、*BSD な場合とかは注意のこと。 今回の環境は Debian GNU/Linux。

useradd とか adduser とか便利になるのは良いけど、紛らわしいコマンドも出来てきて いる為、とても憶えて置けない。だから検索するのだけど、どうにもヒット率が 悪すぎ。なので、めも。

typodupeerror

アレゲはアレゲ以上のなにものでもなさげ -- アレゲ研究家

読み込み中...