C#でWindowsのシステム環境変数を取得するときに値として埋め込まれている環境変数を展開しないで取得する

題名長い (;´д`)

環境変数を取得して改変してセットしたいときに値として埋め込まれた環境変数が展開されてしまうと不都合があると思います。

システム環境変数Pathを取得して変更する例

システム環境変数(例えばPath)を取得したい場合、いくつかやり方があるけど以下のようにすると簡単ですよね。

string env = "Path";
string value = Environment.GetEnvironmentVariable(env, EnvironmentVariableTarget.Machine);
Console.WriteLine(string.Format("{0}={1}", env, value);

以下のような値が取れたとします。

Path=C:\Program Files\Java\jre1.8.0_111\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ProgramData\chocolatey\bin

ただ環境変数GUIから確認すると、以下のようになっています。

Path=%JAVA_HOME%\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ProgramData\chocolatey\bin

取得した値に追加のパスを入れて保存したら%JAVA_HOME%\binC:\Program Files\Java\jre1.8.0_111\binに変わってしまいますよね。これは嬉しくありません。

というわけで、レジストリから取得すれば展開前の値が取れました。

using Microsoft.Win32;

string env = "Path";
RegistryKey reg = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment");
string value = (String)reg.GetValue(env, "", RegistryValueOptions.DoNotExpandEnvironmentNames);
Console.WriteLine(string.Format("{0}={1}", env, value);

GetValueの第3引数にRegistryValueOptions.DoNotExpandEnvironmentNames渡すと展開されずに取得できます。

意外と手こずったのでφ(..)メモメモ

IE 11で何故か互換表示になってしまう場合にデフォルト(Edge)に戻す

会社の中でIE使っているときはイントラネットゾーンになって、なんか互換表示になっていることがあります。

その時は、metaタグに

<meta http-equiv="X-UA-Compatible" content="IE=edge">

と入れることで元に戻るのですが、なんか戻らない時があるんですよね。

そんなときは、上の方(charsetのすぐ下とか)に書いてみると直ることがあります。

<head>
    <meta charset="UTF-8">
    .
    .
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    .

↓↓↓

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    .
    .
    .

まったく、何なんすかねこれヽ(`Д´)ノプンプン

Groovyでログから特定区間の処理時間を計算する

障害調査とかログから処理時間を抽出するというのをごにょっとやったのでメモを残しておきます。(書いとかないと絶対忘れるやつだし)

ログファイルから欲しい情報を抜き出す

スタックトレースを起点に処理時間を抽出しようとするとその行には日付などの情報が入って無くて前後数行欲しいってありますよね。

$ ag --nonumbers -B4 -A1 -G "hogehoge.log*" "^System\.Data\.SqlClient\.SqlException"
  • -B4 は前4行を抜き出すということです
  • -A1 は後1行を抜き出すということです
  • -G正規表現を使うようにしてます

2点間の処理時間を調べる

上で抽出した中間ファイルからExcelで処理するようのCSVを作成します。
使い慣れたGroovyでやってみます。使い捨てのスクリプトなので適当に書いてます。

  • 取り敢えず半角スペースでsplitしながらぐるぐる回します
new File('hogehoge.txt').splitEachLine(' ') { logs ->
    // 処理
}
  • 上の処理の中身(回しながら欲しい2点間のログを抽出)
    def format = "yyyy-MM-dd HH:mm:ss,SSS"

    comment = logs[7]
    if (!comment) {
        //println "null"
    }
    else if (comment.contains("アプリケーションを開始")) {
        start = new Date().parse(format, "${logs[3]} ${logs[4]}")
    }
    else if (comment.contains("DBの接続に失敗しました")) {
        end = new Date().parse(format, "${logs[3]} ${logs[4]}")
        time = end.toTimestamp().getTime() - start.toTimestamp().getTime()
        println "${logs[0]}\t${logs[3]} ${logs[4]}\t${time}"
    }

logs[7]にログの文字列が入ってくる想定なので計測したい2点間のキーワードを引っ掛けて、ログの時間を取得して処理時間を計算します。
この時に、.NETのlog4netで出している形式をformatで定義してData().parseで変換してます。
yyyy-MM-dd HH:mm:ss,SSS こんな形式で実際には2017-01-16 12:34:56,789って感じのやつですね。
timeに処理時間を入れてます。計算するときは、toTimestamp().getTime()を使ってミリ秒単位で結果が出るようにしています。

って言うか、最初からログに処理時間を出すようにして欲しいデス!!!

おまけ

  • ログが巨大なのでちょっと1万行くらい処理して様子をみたいとかあるのですが、Groovyのeachの中ではbreak出来ないので無理やり抜けるようにしてました。
def i = 0
new File('hogehoge.txt').splitEachLine(' ') { logs ->
    // 処理
    i++
    if (i > 10000) { System.exit(0) }
}

他にいいやり方があれば教えて欲しい・・・。

  • 一応、ソース付けておきます。
def i = 0
def format = "yyyy-MM-dd HH:mm:ss,SSS"
def start
def end
def time
def comment

new File('hogehoge.txt').splitEachLine(' ') { logs ->
    comment = logs[7]
    if (!comment) {
        //println "null"
    }
    else if (comment.contains("アプリケーションを開始")) {
        start = new Date().parse(format, "${logs[3]} ${logs[4]}")
    }
    else if (comment.contains("DBの接続に失敗しました")) {
        end = new Date().parse(format, "${logs[3]} ${logs[4]}")
        time = end.toTimestamp().getTime() - start.toTimestamp().getTime()
        println "${logs[0]}\t${logs[3]} ${logs[4]}\t${time}"
    }
    // 1万行ほどやってみるときは下のコメントを外す
    //i++
    //if (i > 10000) { System.exit(0) }
}

iTerm2でvimを使うとマウスでコピペできなくなった

記憶は定かではないがある時を境にでビジュアルモードで選択されるようになった。 最初に何か設定したかもしれないけど思い出せないのでぐぐったら解決した。

d.hatena.ne.jp

ここに書いてあるとおりですが、設定項目は微妙に変わっていて、

  • iTerm2 > Preferences > Profiles > Terminal > Terminal Emulation
    • Enable mouse reporting のチェックを外す

でした。

ubuntuでntpdateを使って時刻合わせをする

会社では、例によってProxyがあるので社内のNTPサーバに同期させる。

/etc/default/ntpdateというファイルがあったので、NTPSERVERSに社内のサーバを記述してntpdateコマンドを叩いてみる

# ntpdate
 4 Jan 11:40:08 ntpdate[23795]: no servers can be used, exiting

うまくいかない・・・

調べたらどうやら/usr/sbin/ntpdate-debianというラッパーコマンドがあるらしい。
ただしこれを使うときは、NTPDATE_USE_NTP_CONF=noにしないと設定したサーバリストが使われない。

# The settings in this file are used by the program ntpdate-debian, but not
# by the upstream program ntpdate.

# Set to "yes" to take the server list from /etc/ntp.conf, from package ntp,
# so you only have to keep it in one place.
#NTPDATE_USE_NTP_CONF=yes
NTPDATE_USE_NTP_CONF=no

# List of NTP servers to use  (Separate multiple servers with spaces.)
# Not used if NTPDATE_USE_NTP_CONF is yes.
#NTPSERVERS="ntp.ubuntu.com"
NTPSERVERS="10.x.x.x"

# Additional options to pass to ntpdate
NTPOPTIONS=""

これで上手くいきました。

# ntpdate-debian
 4 Jan 11:44:30 ntpdate[23814]: step time server 10.x.x.x offset 253.208283 sec

このntpdate-debianは起動時に実行されるらしいので気になる場合はcronで定期実行させてもいいかも。

JIRAの担当者で出て来る一覧をフィルタする

JIRAでLDAP連携をしていると担当者選択でLDAPの全ユーザが出てきてとってもうざい。 ぐぐったらフィルタを掛けることが出来たのでメモしておく。

www.ricksoft.jp

設定

  1. JIRA管理 > 課題 > パーミッションスキーム
  2. 変更したいパーミッションの「権限」を押す
  3. 割当可能なユーザを編集
    • アプリケーションロール(ログイン済みのユーザ全員)が設定されていれば削除する
    • 例えばjira-software-usersだけにするのであれば、グループ(jira-software-users)を選択して許可

これでおっけー。

ちなみにカスタムフィールドの場合はユーザピッカーのカスタムフィールドを作った後で構成から入るとフィルタを設定できました。

パフォーマンス カウンターのDisk Reads/sec, Disk Writes/secの単位ってなんだ?

Windowsのパフォーマンスカウンターをよく使うのですが、説明をしようと思うと意外と曖昧に理解していたり調べてもすぐ忘れてしまうのでメモしておく。

パフォーマンスカウンターを仕掛けるときに定番のものがいくつかあるのですが、ディスクについては\PhysicalDisk(*)\Disk Reads/sec\PhysicalDisk(*)\Disk Writes/secを取って説明資料を作ることがあります。
このカウンターの説明にはそれぞれ、

ディスク上の読み取り操作の速度です。
ディスク上の書き込操作の速度です。

と書いてあるのですが、説明が少なすぎてなんのことだかよく分かりません。
速度の単位は何?と思ってググってもよく分からないです。
Disk Read Bytes/secなら

読み取り操作中にディスクからバイトが転送される速度です。

とあって、まあ分からないでもないです。(若干日本語に違和感を感じますが・・・)

で、結局何なんだというとIOPS(IO Per Second)だということで自分の中で納得しました。
Disk Reads/secなら病患のI/O処理回数ってことになり、数値が高いほど性能が高い(頑張っていっぱい読んでる)ということになりますね。