技術メモ

神奈川在住のITエンジニアの備忘録。おもにプログラミングやネットワーク技術について、学んだことを自分の中で整理するためにゆるゆると書いています。ちゃんと検証できていない部分もあるのでご参考程度となりますが、誰かのお役に立てれば幸いです。

ifTable と ifXTable

SNMPの標準MIB-2配下には、インタフェースを表すMIBテーブルが2つある。ifTable(.1.3.6.1.2.1.2.2) と ifXTable(.1.3.6.1.2.1.31.1.1) である。

http://www.oidview.com/mibs/0/IF-MIB.html

 

ifXTable は、ifTable の後に拡張版として定義されたものであり、64bit型のMIBを扱うことができるため、32bit型のMIBでは扱えない、大容量なネットワークの情報を格納することができる。

https://tools.ietf.org/html/rfc2863

http://net-snmp.sourceforge.net/docs/mibs/ifMIBObjects.html

X-Frame-Options レスポンスヘッダについて

httpの X-Frame-Options レスポンスヘッダについて簡単に纏める。

webサーバがクライアント(ブラウザ)に応答を返す際、そのレスポンスヘッダに「X-Frame-Options」を入れることで、ブラウザ側での iframe(フレーム) の制御をコントロールすることができる。

X-Frame-Options に「DENY」をセットすると、ブラウザ側ではフレーム内のページ表示ができなくなる。「SAMEORIGIN」をセットすると、フレーム内のページのドメインとフレームを包含するページのドメインが同じ場合のみ、フレーム内のページを表示するよう制限できる。

この X-Frame-Options は、「クリックジャッキング」攻撃への webサーバ側の対策として使用されることがある。

 

以下を参考にさせて頂きました。

https://nulab.com/ja/blog/typetalk/measure-clickjacking/

https://cybersecurity-jp.com/security-measures/6935

Javascript で現在時刻を見やすく出力する。

デバッグの一環で、javascript で現在時刻を入れたログをブラウザのコンソールに出力しようとしたら、現在時刻の取得&見やすい形への整形がちょっと面倒だったので、それ用の関数 getCurrentTimeStr() を作成した。これを呼ぶと、戻り値として「2019/04/07 22:17:12.090」のように、人に優しい形式で現在時刻を返す。
以下は、getCurrentTimeStr() を使ったサンプル。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-language" content="ja">
        <meta charset="UTF-8">
        <title>現在時刻</title>
        <script>
            function showCurrentTime() {
             document.getElementById('currentTime').innerHTML = getCurrentTimeStr();
            }

            function getCurrentTimeStr() {
                var currentTime = new Date();
                var year = currentTime.getFullYear();
                var mon = currentTime.getMonth() + 1;
                var day = currentTime.getDate();
                var hour = currentTime.getHours();
                var min = currentTime.getMinutes();
                var sec = currentTime.getSeconds();
                var millsec = currentTime.getMilliseconds();
                
                if(mon < 10) {
                    mon = "0" + mon;
                }
                if(day < 10) {
                    day = "0" + day;
                }
                if(hour < 10) {
                    hour = "0" + hour;
                }
                if(min < 10) {
                    min = "0" + min;
                }
                if(sec < 10) {
                    sec = "0" + sec;
                }
                if(millsec < 10) {
                    millsec = "00" + millsec;
                }
                else if (10 <= millsec && millsec < 100) {
                    millsec = "0" + millsec;
                }
                
                var currentTimeStr = year + "/" + mon + "/" + day + " " + hour + ":" + min + ":" + sec + "." + millsec;
                return currentTimeStr;
            }
        </script>
    </head>
    <body>
        <input type="button" value="現在時刻" onclick="showCurrentTime()">
        <div id="currentTime"></div>
    </body>
</html>

getCurrentTimeStr() 内では、桁数が揃うように、必要に応じて上位の桁を "0" で埋めている。

Javaの例外設計

Javaでプログラミングしていると、どこでどの例外をキャッチすべきか悩むことが多い。特にチェック例外はどこかにキャッチ処理を書かないとコンパイルが通らないので、その数が増えるとコードがキャッチ処理で埋め尽くされて煩雑になってしまう。

 

この悩みに対しては、最近はフレームワークなどで用いられている以下の設計が良いと思っている。

  • チェック例外をキャッチしたら、専用の非チェック例外に包んで(例外翻訳して)、上位に投げる。
  • 上位のある個所で、纏めて専用の非チェック例外をキャッチして処理する。もちろん、個別に対処すべき例外があるなら、それは個別の catch 節を設けて対応する。
  • チェック例外が発生する箇所で対処できる&すべきであるなら、上記はせずにその場でキャッチして対処する。

この方法なら、コードが大量の throws 節や catch節に覆われることもなく、例外処理が纏まるのでコードも見やすくなるはず。

nslookupコマンドは hosts ファイルを参照しない。

先日、hosts ファイルを書き換えたものの、それが nslookup コマンドの結果に反映されなかったので「あれ?」と思って調べたら、このコマンドは hosts ファイルを参照しないらしい。

https://tech.nikkeibp.co.jp/it/article/COLUMN/20070312/264620/

https://tech.nikkeibp.co.jp/it/article/COLUMN/20060321/232901/

 

WindowsでもLinuxでも、nslookup コマンドは、DNSサーバに名前解決を問い合わせるだけで、hosts ファイルなど、他の名前解決の手段は参照しないらしい。

Pythonでグローバル変数を更新する

最近、Pythonの勉強を始めた。Pythonを勉強していくなかで、これまで使ってきた言語 (JavaPerlやC) と違う点について、少しずつメモしていこうと思う。
まずは、Pythonにおけるグローバル変数の変更について。

Pythonで関数内からグローバル変数変更する際は、関数内で「global グローバル変数名」として宣言する必要がある。関数内からグローバル変数を参照するだけなら、「global」を付ける必要はない。以下は、そのテストプログラム。

# グローバル変数
var = 'aaa'

def func0():
    print(var) # aaa

def func1():
    var = 'bbb'

def func2():
    global var
    var = 'ccc'

func0()

func1()
print(var) # aaa

func2()
print(var) # ccc

func2 内では、「global」を付けているので、グローバル変数 var を変更している。func1 内では、「global」を付けていないので、ローカル変数の var に対して操作していることになる。

Pythonでは、グローバル変数の意図しない変更でバグを作り込まないように、このような言語仕様になっていると考えている。

Javaで時刻間の差分を出す

Javaで引数で受け取った2つの時刻間の差分を出すプログラム(calcTimeDiff)を作成した。ログ解析などをしていて、ログ内のある時刻からある時刻までの正確な経過時間が欲しい時、脳内でいちいち計算するのが面倒だったので、これを作成した。

使い方は、
java calcTimeDiff "開始時刻" "終了時刻"
で、"開始時刻" と "終了時刻" との差分を出す。

例えば、
java calcTimeDiff "2019/03/24 22:00:00" "2020/03/24 22:20:30"
として実行すると、結果は、
Diff Time: 366 days 0 hours 20 minutes 30 seconds
となる。

なお、対応している引数の時刻の形式は以下。
yyyy/MM/dd HH:mm:ss (例:2019/03/24 22:00:00)
yyyy/MM/dd HH:mm (例:2019/03/24 22:00)
yyyy/MM/dd HH (例:2019/03/24 22)
yyyy/MM/dd (例:2019/03/24)

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

public class calcTimeDiff {
    public static void main(String[] args) {
        if (args.length != 2) {
            throw new IllegalArgumentException("Both start date and end date are necessary.");
        }
        String startDateStr = args[0];
        String endDateStr   = args[1];
        long timeDiff = getEpochTime(endDateStr) - getEpochTime(startDateStr);

        if (timeDiff < 0) {
            throw new IllegalArgumentException("End date should be later than start date.");
        }
        printTimeDiff(timeDiff);
    }

    private static void printTimeDiff (long timeDiff) {
        int ONE_MIN_MILL_SEC_TIME   = 1000 * 60;
        int ONE_HOUR_MILL_SEC_TIME  = 1000 * 60 * 60;
        long ONE_DAY_MILL_SEC_TIME  = 1000 * 60 * 60 * 24;

        long days = timeDiff / (ONE_DAY_MILL_SEC_TIME);
        int restExceptDays = (int)(timeDiff % (ONE_DAY_MILL_SEC_TIME));
        int hours = restExceptDays / ONE_HOUR_MILL_SEC_TIME;
        int restExceptHours = restExceptDays % (ONE_HOUR_MILL_SEC_TIME);
        int mins = restExceptHours / ONE_MIN_MILL_SEC_TIME;
        int restExceptMins = restExceptHours % (ONE_MIN_MILL_SEC_TIME);
        int seconds = restExceptMins / 1000;

        System.out.printf("Diff Time: %d days %d hours %d minutes %d seconds", days, hours, mins, seconds);
    }

    private static long getEpochTime (String dateStr) {
        List<SimpleDateFormat> formatters = new ArrayList<SimpleDateFormat>();
        formatters.add(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"));
        formatters.add(new SimpleDateFormat("yyyy/MM/dd HH:mm"));
        formatters.add(new SimpleDateFormat("yyyy/MM/dd HH"));
        formatters.add(new SimpleDateFormat("yyyy/MM/dd"));

        long epochTime = 0;
        int counter = 0;
        for (SimpleDateFormat formatter : formatters) {
            try {
                epochTime = formatter.parse(dateStr).getTime();
                break;
            }
            catch (ParseException ex) {
                counter++;
                if (counter >= formatters.size()) {
                    throw new IllegalArgumentException("Failed to format the input date", ex);
                }
            }
        }
        return epochTime;
    }
}