検討前の対策案
データベースサーバーのタイムゾーン(=DBTIMEZONE)を UTC にして、ローカルタイムはアプリケーション側で対処する。
Oracle がもつ何かしらの時刻システムを利用する。
時刻型は使用せず文字列型で頑張る。(外道?)
検討後の個人的な結論
DBTIMEZONE の設定は変えない。
Timestamp with local time zone 型が扱いやすそう。
Date 型や Timestamp 型は使わないほうがよさそう。
結論に至るまでの考察。
Date 型や Timestamp 型について。
Date 型や Timestamp 型は、そもそもタイムゾーン情報を持ち合わせていないので、その記録時刻がどのタイムゾーンに属するのかを判定することができない。
同様に、よく使われる sysdate, systimestamp が戻す型は Date 型, Timestamp 型であるためタイムゾーンを持たない。
sysdate, systimestamp が戻す時刻は database のマシンの locale 情報に基づいている。このため ORA_SDTZ の設定(*1) を替えても、あくまで database が動作している PC の timezone での時刻が戻される。
(*1) 環境変数 ORA_SDTZ にタイムゾーンを指定することで、セッション(=クライアント)のタイムゾーンを変えることができる。
Timestamp with time zone 型について。
タイムゾーン情報を記録する。
記録されたタイムゾーンは insert したセッションのタイムゾーンが記録される。このため UTC で同じ時刻であっても違う時刻として記録される。たとえば 09:00 +09:00 と 19:00 -05:00 はともに UTC 0:00 だが違うものとして扱われる。
記録したデータを、他のタイムゾーンから読みだした場合、記録時のタイムゾーンの表記で読みだされる。+09:00 のセッションから -05:00 で記録したデータを読みだした場合、09:00 ではなく 19:00 -05:00 が得られる。
Timestamp with local time zone 型について。
データベースのタイムゾーンに変換して記録される。
このため、insert したセッションのタイムゾーンに関わりなく、読みだし時にそのクライアント側のタイムゾーンの時刻に変換される。
ここまでの要点
DATE型 / TIMESTAMP型はタイムゾーン情報が失われる。
Timestamp with time zone 型は Insert したクライアントのタイムゾーン情報も記録される。
Timestamp with local time zone 型は読み出し時にクライアントのタイムゾーンに変換されて表示される。
SYSDATE / SYSTIMESTAMP はクライアントのタイムゾーンが何であれ、常にデータベースサーバーのタイムゾーンの値で記録され、かつタイムゾーン情報は失われる。
挙動の確認
準備とか
テスト用のテーブルを作成する
create table TIME (
ID number(2),
DT date,
TS timestamp,
TSL timestamp with local time zone,
TSTZ timestamp with time zone
);
表示を見易くするための設定など
ALTER SESSION SET NLS_DATE_FORMAT = 'RR-MM-DD HH24:MI:SS';
set TAB off
set LINESIZE 300
col SYSTIMESTAMP for A32
col CURRENT_TIMESTAMP for A32
col TS for A25
col TSL for A25
col TSTZ for A32
col SESSIONTIMEZONE for A17
それぞれのクライアントでデータベースタイムゾーン/セッションタイムゾーンを確認
+09:00 側クライアントで確認
SQL> select DBTIMEZONE,SESSIONTIMEZONE from dual;
DBTIMEZONE SESSIONTIMEZONE
------------ -----------------
+00:00 +09:00
SQL> select SYSDATE, CURRENT_DATE, SYSTIMESTAMP, CURRENT_TIMESTAMP from DUAL;
SYSDATE CURRENT_DATE SYSTIMESTAMP CURRENT_TIMESTAMP
----------------- ----------------- -------------------------------- --------------------------------
15-01-06 00:35:01 15-01-06 00:35:01 15-01-06 00:35:01.865000 +09:00 15-01-06 00:35:01.865000 +09:00
-05:00 側クライアントで確認
SYSDATE, SYSTIMESTAMP はクライアント側のタイムゾーンではなく、Database 側のタイムゾーンの時刻になっていることに注目します。
SQL> select DBTIMEZONE,SESSIONTIMEZONE from dual;
DBTIMEZONE SESSIONTIMEZONE
------------ -----------------
+00:00 -05:00
SQL> select SYSDATE, CURRENT_DATE, SYSTIMESTAMP, CURRENT_TIMESTAMP from DUAL;
SYSDATE CURRENT_DATE SYSTIMESTAMP CURRENT_TIMESTAMP
----------------- ----------------- -------------------------------- --------------------------------
15-01-06 00:19:46 15-01-05 10:19:46 15-01-06 00:19:46.649000 +09:00 15-01-05 10:19:46.649000 -05:00
CURRENT_TIMESTAMP を INSERT
TSTZ 列は UTC としては同一時刻でも表記が異なる点に注目します。TSL 列はクライアント側のローカル時刻として表示されます。DT 列と TS 列は Insert したクライアントのローカル時刻で表示されますが、どのクライアントから Insert したかの情報(=タイムゾーン情報)は記録されていないため、時系列,発生順にソートすることができない記録になっていることに注目します。
+09:00 側クライアントで操作
SQL> insert into TIME values (1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
SQL> commit;
-05:00 側クライアントで操作
SQL> insert into TIME values (2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
SQL> commit;
+09:00 側クライアントで確認
SQL> select * from TIME;
ID DT TS TSL TSTZ
-- ----------------- ------------------------- ------------------------- --------------------------------
1 15-01-06 00:29:53 15-01-06 00:29:53.006000 15-01-06 00:29:53.006000 15-01-06 00:29:53.006000 +09:00
2 15-01-05 10:29:53 15-01-05 10:29:53.488000 15-01-06 00:29:53.488000 15-01-05 10:29:53.488000 -05:00
-05:00 側クライアントで確認
SQL> select * from TIME;
ID DT TS TSL TSTZ
-- ----------------- ------------------------- ------------------------- --------------------------------
1 15-01-06 00:29:53 15-01-06 00:29:53.006000 15-01-05 10:29:53.006000 15-01-06 00:29:53.006000 +09:00
2 15-01-05 10:29:53 15-01-05 10:29:53.488000 15-01-05 10:29:53.488000 15-01-05 10:29:53.488000 -05:00
SYSTIMESTAMP を INSERT
TSL 列はローカル時刻が表示されます。DT 列と TS 列は常に +09:00 (=DBTIMEZONE) で表示されます。TSTZ 列は SYSTIMESTAMP のタイムゾーン(=+9:00)で表示されます。
+09:00 側クライアントで操作
SQL> insert into TIME values (3, SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
SQL> commit;
-05:00 側クライアントで操作
SQL> insert into TIME values (4, SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP, SYSTIMESTAMP);
SQL> commit;
+09:00 側クライアントで確認
SQL> select TIME.*, CURRENT_TIMESTAMP from TIME;
ID DT TS TSL TSTZ CURRENT_TIMESTAMP
-- ----------------- ------------------------- ------------------------- -------------------------------- --------------------------------
3 15-01-06 00:45:17 15-01-06 00:45:17.809000 15-01-06 00:45:17.809000 15-01-06 00:45:17.809000 +09:00 15-01-06 00:54:34.766000 +09:00
4 15-01-06 00:45:18 15-01-06 00:45:18.349000 15-01-06 00:45:18.349000 15-01-06 00:45:18.349000 +09:00 15-01-06 00:54:34.766000 +09:00
-05:00 側クライアントで確認
SQL> select TIME.*, CURRENT_TIMESTAMP from TIME;
ID DT TS TSL TSTZ CURRENT_TIMESTAMP
-- ----------------- ------------------------- ------------------------- -------------------------------- --------------------------------
3 15-01-06 00:45:17 15-01-06 00:45:17.809000 15-01-05 10:45:17.809000 15-01-06 00:45:17.809000 +09:00 15-01-05 10:55:14.351000 -05:00
4 15-01-06 00:45:18 15-01-06 00:45:18.349000 15-01-05 10:45:18.349000 15-01-06 00:45:18.349000 +09:00 15-01-05 10:55:14.351000 -05:00
総論
結論的にはシステムで強くタイムゾーンを意識する必要がある場合は Timestamp with time zone 型を使用します。そうではなく、システム内では一貫した時刻を管理するが、クライアント側の表示はローカル時刻で表示したい、という場合は Timestamp with local time zone 型を使うのが手軽である気がします。
その他、時刻関連の注意事項
時刻データ型のサイズ
それぞれのデータ型のサイズは以下の通りです。
データ型
サイズ
Date 型
7 Byte
TimeStamp 型
7 Byte or 11 Byte
Timestamp with time zone 型
13 Byte
Timestamp with local time zone 型
7 Byte or 11 Byte
公式ドキュメントは https://docs.oracle.com/cd/E16338_01/server.112/b56299/sql_elements001.htm などを参照。
また更新ドキュメントを参照すると、タイムスタンプ型は TIMESTAMP [(fractional_seconds_precision)] という書き方ができ、精度の指定とそれによりサイズが変わる模様です。
データベースのタイムゾーン(=DBTIMEZONE)が異なるサーバー間の Export/Import
ここではテーマにしていませんが、DATE 型や TIMESTAMP 型の列は、Export したデータベースのタイムゾーンと Import するデータベースのタイムゾーンが異なると、時刻の意味が変わります。(Timezone の時刻差だけズレてしまう)
そのようなデータ交換をする可能性があるシステムの場合は imestamp with local time zone 型または Timestamp with local time zone 型を使ったほうがよさそうです。
posted in Oracle , 時刻 by ooltcloud | No Comments
2020年7月26日
Windows 7 + Oracle 11gR2 時代のプログラムをリビルドすることなく Windows 10 で動作させたいのですが、ODP.NET の 11.2 は Windows 10 非対応です。そこで Windows 10 対応の ODAC を使い、ODP 11.2 のプログラムを動作させるための設定を行ってみました。
Oracle ODAC Xcopy のインストール
まず Oracle ODAC のインストールを行います。
Windows 10 で動作させたいので、Windows 10 対応されている ODAC のうち今回は 18.3 を使用することにします。
「ODAC Runtime Downloads」で検索し、https://www.oracle.com/database/technologies/dotnet-odacdeploy-downloads.html にアクセスします。
下にスクロールさせていくと、ODAC Xcopy というセクションがあります。ここで任意のバージョンのランタイムを取得します。今回は 32bit の ODAC 18.3 を選択します。
C++ 再頒布可能パッケージ をダウンロードします。
ODAC をインストールするためには、バージョンに対応した C++ 再頒布可能パッケージが必要です。
下にスクロールさせていくとリンクがあるので、対応したバージョンの C++ 再頒布可能パッケージ を Microsoft のサイトからダウンロードします。
今回は 18.3 なので 2013 の C++ 再頒布可能パッケージ をダウンロードします。
(以前の記事「Instant Client のインストール (11.2 for Windows) 」ではこの記載がありませんが、この時の環境は Visual Studio がすでにインストールされた環境であったため、あらためてインストールする必要がなかったのだと思われます・・・ -_-;)
リンク先に「Microsoft Visual C++ Redistributable Packages for Visual Studio 2013」があるのでそれを選択します。
ダウンロードした C++ 再頒布可能パッケージをインストールします。
ダウンロードした ODAC Runtime を解凍しインストールします。
インストール先と Oracle Home 名は自由に設定できます。今回は c:\oracle\product\18.3\odac、Oracle Home 名は odac183 にします。
また、ODP.NET 2 と ODP.NET 4 をインストールするので、以下のように 2 回インストーラーを実行します。
また、コマンドプロンプトは管理者で実行し、ODAC Xcopy を解凍したディレクトリをカレントにおいておきます。
C> install.bat odp.net2 c:\oracle\product\18.3\odac odac183 true
C> install.bat odp.net4 c:\oracle\product\18.3\odac odac183 true
インストールが終了すると、Path に定義を先頭に追加します。
C:\oracle\Product\18.3\odac
C:\oracle\Product\18.3\odac\bin
ちなみに上記の画面キャプチャだと 3 行目に C:\oracle\Product\18.0.0\dbhomeXE\bin というのがいますが、ここれはインストール PC に Oracle XE 18c をインストールしていたためで、今回の作業とは関係ありません。
インストール先にある oracle.key を参照し、レジストリを変更します。
接続先データベースの NLS_LANG にあわせます。今回は Oracle XE に接続こともあり、NLS_LANG を JAPANESE_JAPAN.AL32UTF8 に変更します。
接続先を TNSNAMES.ORA に設定します。
本来は C:\oracle\product\18.3\odac\network\admin\ に tnsnames.ora を書くべきですが、今回の PC には Oracle XE がインストールされていた手前、二重管理が面倒なので XE 側の tnsnames.ora にリンクを貼ることでお茶を濁します(汗
C> mklink C:\oracle\product\18.3\odac\network\admin\tnsnames.ora C:\oracle\product\18.0.0\dbhomeXE\network\admin\tnsnames.ora
ODP.NET 11.2 のリダイレクト設定
次に ODP.NET 11.2 のプログラムが ODP.NET 18.3 の Oracle.DataAccess.dll をロードするための設定を行います。
また以下では Oracle Home ディレクトリを %ORACLE_HOME% と表現しています。今回の場合は上記インストールで指定した c:\oracle\product\18.3\odac になります。
GAC に 18.3 の Oracle.DataAccess.dll を登録します。
.net2 用, .net4用の Oracle.DataAccess.dll を GAC に登録します。
Oracle.DataAccess.dll の場所は %ORACLE_HOME%\odp.net\bin です。
その際、OraProvCfg.exe を使用しますが、ファイル名は同じですが中身は .net2 用, .net4用で異なるようなので、それぞれのフォルダにある OraProvCfg.exe を使用します。
C> C:\oracle\product\18.3\odac\odp.net\bin\2.x\OraProvCfg.exe /action:gac /providerpath:C:\oracle\product\18.3\odac\odp.net\bin\2.x\Oracle.DataAccess.dll
C> C:\oracle\product\18.3\odac\odp.net\bin\4\OraProvCfg.exe /action:gac /providerpath:C:\oracle\product\18.3\odac\odp.net\bin\4\Oracle.DataAccess.dll
11.2 用の発行者ポリシーを GAC に登録します。
.net2 用, .net4用の Policy.2.112.Oracle.DataAccess.dll を GAC に登録します。
Policy.2.112.Oracle.DataAccess.dll の場所は %ORACLE_HOME%\odp.net\PublisherPolicy です。
その際、OraProvCfg.exe を使用しますが、ファイル名は同じですが中身は .net2 用, .net4用で異なるようなので、それぞれのフォルダにある OraProvCfg.exe を使用します。
C> C:\oracle\product\18.3\odac\odp.net\bin\2.x\OraProvCfg.exe /action:gac /providerpath:C:\oracle\product\18.3\odac\odp.net\PublisherPolicy\2.x\Policy.2.112.Oracle.DataAccess.dll
C> C:\oracle\product\18.3\odac\odp.net\bin\4\OraProvCfg.exe /action:gac /providerpath:C:\oracle\product\18.3\odac\odp.net\PublisherPolicy\4\Policy.4.112.Oracle.DataAccess.dll
セットアップ失敗事例
以下のようなエラーが表示された場合、セットアップに失敗しているかもしれません。
GAC に登録していない
「ファイルまたはアセンブリ、またはその依存関係の 1 つが読み込めませんでした。」が表示される場合、GAC への Oracle.DataAccess.dll 本体または発行者ポリシー(Policy.X.XXX.Oracle.DataAccess.dll)の登録に失敗しているかもしれません。
ハンドルされていない例外: System.IO.FileNotFoundException: ファイルまたはアセンブリ 'Oracle.DataAccess, Version=4.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見 つかりません。
場所 ConsoleApplication1.Module1.Main()
64bit の DLL をロードしている
「間違ったフォーマットのプログラムを読み込もうとしました。」が表示される場合、違うプラットフォームの DLL を読み込んでいる可能性があります。今回の場合は 32 bit の DLL をロードするはずが 64 bit の DLL をロードしている可能性があります。GAC に登録した DLL のプラットフォーム(32bit or 64bit)や Path の登録, 順序等を再確認してください。
ハンドルされていない例外: System.TypeInitializationException: 'Oracle.DataAccess.Client.OracleConnection' のタイプ初期化子 が例外をスローしました。 ---> System.BadImageFormatException: 間違ったフォーマットのプログラムを読み込もうとしました。 (HRESULT からの例外:0x8007000B)
場所 Oracle.DataAccess.Client.OpsInit.CheckVersionCompatibility(String version)
場所 Oracle.DataAccess.Client.OracleInit.Initialize()
場所 Oracle.DataAccess.Client.OracleConnection..cctor()
--- 内部例外スタック トレースの終わり ---
場所 Oracle.DataAccess.Client.OracleConnection..ctor(String connectionString)
C++ 再頒布可能パッケージをインストールしていない。
「'OraOpsXX.dll' を読み込めません:指定されたモジュールが見つかりません」が表示される場合、C++ 再頒布可能パッケージ をインストールしていないか、違うバージョンをインストールしている可能性があります。インストールした C++ 再頒布可能パッケージがインストールした ODAC が指定したバージョンと同じかどうかを確認してください。
ハンドルされていない例外: System.TypeInitializationException: 'Oracle.DataAccess.Client.OracleConnection' のタイプ初期化子 が例外をスローしました。 ---> System.DllNotFoundException: DLL 'OraOps12.dll' を読み込めません:指定されたモジュールが見つかりません。 (HRESULT からの例外:0x8007007E)
場所 Oracle.DataAccess.Client.OpsInit.CheckVersionCompatibility(String version)
場所 Oracle.DataAccess.Client.OracleInit.Initialize()
場所 Oracle.DataAccess.Client.OracleConnection..cctor()
--- 内部例外スタック トレースの終わり ---
場所 Oracle.DataAccess.Client.OracleConnection..ctor(String connectionString)
Path が設定されていない
「オブジェクト参照がオブジェクトインスタンスに設定されていません。」が表示される場合、%ORACLE_HOME% および %ORACLE_HOME%\bin への PATH が設定されていない可能性があります。PATH の定義を確認してください。
ハンドルされていない例外: System.NullReferenceException: オブジェクト参照がオブジェクト イ ンスタンスに設定されていません。
場所 Oracle.DataAccess.Client.OracleException.get_Number()
場所 Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck, Int32 isRecoverable, OracleLogicalTransaction m_OracleLogicalTransaction)
場所 Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, Object src, OracleLogicalTransaction m_oracleLogicalTransaction)
場所 Oracle.DataAccess.Client.OracleConnectionOCP.Open(OracleConnection con)
場所 Oracle.DataAccess.Client.OracleConnection.Open()
tnsnames.ora がない
「TNS: 指定された接続識別子を解決できませんでした」が表示される場合、%ORACLE_HOME%network\admin\ に tnsnames.ora が作成されていない可能性があります。当該フォルダに tnsnames.ora が存在するかを確認してください。また作成していた場合、指定した接続識別子のエントリーが記載しているかを確認してください。
ハンドルされていない例外: Oracle.DataAccess.Client.OracleException: ORA-12154: TNS: 指定された接続識別子を解決できませんで した
場所 Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck, Int32 isRecoverable, OracleLogicalTransaction m_OracleLogicalTransaction)
場所 Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, Object src, OracleLogicalTransaction m_oracleLogicalTransaction)
場所 Oracle.DataAccess.Client.OracleConnectionOCP.Open(OracleConnection con)
場所 Oracle.DataAccess.Client.OracleConnection.Open()
tnsnames.ora に誤り
「ORA-12545: ターゲット・ホストまたはオブジェクトが存在しないため、接続に失敗しました」が表示される場合、%ORACLE_HOME%network\admin\tnsnames.ora の定義内容に誤りがある可能性があります。定義内容を再確認してください。
ハンドルされていない例外: Oracle.DataAccess.Client.OracleException: ORA-12545: ターゲット・ホストまたはオブジェクトが存在しないため、接続に失敗しました
場所 Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck, Int32 isRecoverable, OracleLogicalTransaction m_OracleLogicalTransaction)
場所 Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, Object src, OracleLogicalTransaction m_oracleLogicalTransaction)
場所 Oracle.DataAccess.Client.OracleConnectionOCP.Open(OracleConnection con)
場所 Oracle.DataAccess.Client.OracleConnection.Open()
posted in Oracle by ooltcloud | 1 Comment
2020年7月25日
テスト環境などで、どうしてもネットワークから時刻が取得できない状況があり、そうはいっても PC 本体のクロックに依存すると標準時との誤差が分単位で出てしまうので、せめて数秒内の誤差で運用したいことがあります。ということで時刻サーバーを導入・・・といってもあれはうん十万するような代物なのでカジュアルには導入できません(汗
そこで GPS の USB ドングルであれば比較的安価に入手できるので、それを使って時刻を取得する方法を考えてみます。
今回は Vk-172 なる USB GPS ドングルが入手できたのでそれを使用して時刻を取得してみます。
USB ドングルを挿すと COM ポートとして認識するので、その COM ポートに teraterm などで接続すると 1 秒に一度テキストが送信されてきます。
流れてくるテキストのうち、先頭が $GPRMC のものに注目します。テキストは CSV 形式になっており 2 列目が時刻(UTC), 10列目が日付です。また 3 列目がステータスで有効(=A),警告(=V) などを表すようです。
$GPRMC,143116.00 ,V ,,,,,,,110919 ,,,N*7C
これは NMEA フォーマットというらしく、フォーマットの詳細は https://www.hiramine.com/physicalcomputing/general/gps_nmeaformat.html などが詳しいのでそちらを参照してください。
このテキストを拾って時刻を取得,設定する Powershell Script が以下です。
https://gist.github.com/ooltcloud/c780872fbbe5248bb782ef9b0401e8d2
警告もお構いなしで、日付と時刻が受信出来たら即時刻設定、という凶悪(?)な仕様になっているので、ご使用の際は気を付けてください(汗
tags: Windows で時刻あわせ posted in OS , Windows , 時刻 , 環境設定 by ooltcloud | No Comments
2020年7月25日
前回記事「Windows で時刻あわせ (6) w32tm (スタンドアロン時刻サーバー)」はこちら 。
時刻同期関連の Powershell Script を置いておきます。
nict.jp が提供する http による時刻配信を利用して時刻を同期する。
https://gist.github.com/ooltcloud/20e7d7551007370b4b8e345499d79cb3
windows time サービス (w32time/w32tm) で同期したほうがよいのは確かですが、windows time サービスによる時刻同期の設定自体が難しくてどうしても時刻同期させられない場合とか、ntp のポート (port 123) が閉じられていて同期できない場合などで、ともかく精度は問わないし時刻も戻ってもいいから(急変していいから)手早く時刻を合わせたい、という場合を想定しています。要管理者権限です。また Invoke-WebRequest が必要なので Powershell 3.0 以上の環境が必要です。(つまり Windows 7 / 2008R2 では動かない場合があります。Powershell の Version は $PSVersionTable で知ることができます。)
とはいえ先般、当該サービスは停止の方向というアナウンスがされたので、これに頼らないほうが良いですね・・・(汗
https://jjy.nict.go.jp/httphttps-index.html
ネットワークを利用した時刻配信におけるNTPへの一元化
~ http/httpsを利用した時刻配信の停止に向けた取組み~
NICTでは、日本標準時を生成すると共に、標準電波、光テレホンJJY、NTP等様々な方法で正確な時刻を配信しています。このうちインターネット上での配信については、NTPに加えてhttp/httpsによる時刻配信を試験的に実施してきましたが、今後別記の理由により「NTPを利用した時刻配信」に一元化する方向とし、「http/httpsを利用した時刻配信」については、停止に向けた取組みを開始させていただきます。
NTP (UDP) を利用して時刻を同期する。(step 調整, Leap Indecator 等無視)
https://gist.github.com/ooltcloud/620831658a0cd9055f53ae3ba3543ee1
上記で「いやそうじゃない、http じゃなくて ntp のままサクッと時刻合わせがしたいんである」という人向け。
そういうひとは桜時計( https://www.vector.co.jp/soft/win95/personal/se050672.html ) を使えって話なんだけども、実行または常駐しているのが見えるのは嫌だとか Windows 標準機能でなんとかならないか(フリーソフトは持ち込めない)という人向け。
そんなニーズがあるのかどうかは知らないが(汗
Powershel version 3 以上が必要です。(-shl などを使っているため。ここを書き換えると version 2 でも動くかも?)
時刻サーバーの情報を確認する。
https://gist.github.com/ooltcloud/1ed59c8ff72a24b273269aa403f6b01f
同期先 NTP サーバーの stratum や ルート分散 (Dispersion) を確認する用途で使用します。
使用方法、表示例は以下のような感じ。
PS >QueryNTPStatus "ntp.nict.jp"
ntp.nict.jp
閏インジケーター : 0 (警告なし)
階層 : 1 (1次参照。原子時計等を参照)
モード : 4 (Server)
精度 : -20
ルート遅延 : 0
ルート分散(拡散) : 0
参照 ID : 0x5443494E (NICT)
時刻源参照時刻 (JST) : 2020/07/24 20:52:32.000 (3804580352)
要求送信時刻 (JST) : 2020/07/24 20:52:31.455 (3804580351.45544)
要求受信時刻 (JST) : 2020/07/24 20:52:32.237 (3804580352.23683)
応答送信時刻 (JST) : 2020/07/24 20:52:32.237 (3804580352.23683)
tags: Windows で時刻あわせ posted in OS , Windows , 時刻 , 環境設定 by ooltcloud | No Comments
2020年7月25日
前回記事「Windows で時刻あわせ (5) w32tm (トラブル事例)」はこちら 。
【注意と免責】
以下の内容は個人的な見解であり正しさを保証しません。正しさを必要とする場合は他のサイトの記事を参照してください。
閉域のネットワーク環境で。とある Windows 端末を時刻マスターとし、閉域ネットワークに接続されているその他の端末の時刻をその時刻マスターと同期させたい、という要求が稀にあります。
ろくなことにならないので、そのような要求は全力で退けましょう(何
本気でそのような要求があるのであれば、Windows を時刻マスターにするのではなく、タイムサーバー製品の導入を検討しましょう。価格がうん十万円とかしますし、設置(アンテナ等)も面倒ですが・・・(汗
それでもなんとか Windows を時刻マスターにしたいのである、という場合、クリアしないとならない問題があります。
時刻マスターとなる時刻サーバーを、信頼性の高い時刻サーバーとなるように設定する。
時刻マスターとなる時刻サーバーは同期先がありません。なので、時刻同期していなくても時刻同期しているフリをする必要があります。(詳しくは「Windows で時刻あわせ (3) w32tm (Server 側) 」を参照)
具体的には以下の設定を行います。
C> w32tm /config /update /reliable:yes /LocalClockDispersion:0
KB232488 問題に対応する。
外部と同期していない場合(同期する時刻サーバーがなんらかの原因で通信できない状況であるとき)、Windows タイムデーモン(Windows Time とは別のサービスと思われる)は 1 時間に 1 回システムクロック(= Free-Running System Clock)とハードウェアクロック(=LOCAL CMOS Clock =RTC)を比較します。その結果 60 秒以上の時間差がある場合、強制的にシステムクロックの値をハードウェアクロックの値に上書きします。つまり、時刻が 1 分進んだり戻ったりします。STEP 調整で 1 分前後するので阿鼻叫喚間違いなしです(汗
KB232488 の文書(http://support.microsoft.com/kb/946033 )に書かれている仕様なのですが、当該文書は 2020/7 現在、非公開になっているようです。
今回時刻マスターにしたい Windows は外部の時刻サーバーと同期していないので、この現象が発生します。
対策は以下の3通りです。
なにもしない
時刻マスターは 1 分の急変が発生しますが、時刻クライアントは slew 調整をすると思われるので急変からは免れることを期待します。
欠点は恐らく時刻クライアント間で時刻が一致しないことです。(時刻マスターの時刻が急変したタイミングでクライアントが一斉に時刻調整を始めるわけではないため。時刻クライアントは時刻マスターの時刻を毎秒単位で確認しているわけではありません。)
定期的に時刻を再設定する
RTC とシステムクロックの差が 60 秒を超えないタイミングで時刻を再設定します。
コマンドプロンプトの TIME コマンドで時刻を設定する場合、コマンド実行直後に設定時刻を RTC に書き込みます。これをタスクスケジューラーを使用して定期的に行うことで RTC とシステムクロックの差が大きくならないようにします。
欠点は恐らく、時刻再設定のタイミングで微小な時刻(システムクロック)の巻戻りがあり、微小ではあるものの同じ時刻を二度繰り返すことと、その微小な誤差が累積されていくことで標準時との誤差が拡大することが予想されることです。
「自動的な時刻補正」を無効にする
timeadjx(http://www.monyo.com/technical/products/timeadjx/ )のような外部ツールを使用して RTC とシステムクロックの時差チェックを無効にします。
C> timeadjx.exe set 156000
欠点は Windows 標準でないツールを使用しなくてはならなくなることです。また同様の処理は w32tm の内部でも行っている(例えば slew 調整では上記の 156000 の値を微調整することで進めたり遅らせたりをしている)はずなので処理が競合するかもしれません。具体的には「自動的な時刻補正」を無効にしていたつもりが、その後に w32tm などの他のプロセスが後から有効に変えていた、などです。
こんなことまでして Windows を時刻マスターにすることが良いのか?というと謎なので、そのような要求があれば今一度よく考えてから対処するようにしましょう。
さて、ここで諸悪の元凶(?)となっている KB232488 の動作を確認してみます。
上位の時刻サーバーとの同期を切断します。
ピア(上位の時刻サーバー)の登録を削除し、時刻ソースが「Local CMOS Clock」か「Free-running System Clock」であることを確認します。同期先サーバーを設定している場合は、存在しないアドレスに変えるかレジストリのエントリー(\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters\NtpServer)を削除(空文字に)するかします。
C>w32tm /query /status
閏インジケーター: 0 (警告なし)
階層: 1 (主参照 - 電波時計で同期)
精度: -6 (ティックごとに 15.625ms)
ルート遅延: 0.0000000s
ルート分散: 10.0000000s
参照 ID: 0x4C4F434C (ソース名: "LOCL")
最終正常同期時刻: 2020/07/18 12:53:39
ソース: Local CMOS Clock
ポーリング間隔: 10 (1024s)
C>w32tm /query /status
閏インジケーター: 3 (最後の 1 分間は 61 秒)
階層: 0 (未指定)
精度: -6 (ティックごとに 15.625ms)
ルート遅延: 0.0000000s
ルート分散: 10.0000000s
参照 ID: 0x00000000 (未指定)
最終正常同期時刻: 2020/07/18 12:53:39
ソース: Free-running System Clock
ポーリング間隔: 10 (1024s)
ちなみに「Local CMOS Clock」と「Free-running System Clock」の違いは以下のような感じです。
Local CMOS Clock
PC 起動直後、およびその状態から時刻サーバーと同期がとれなくて 24 時間未満のときの表示。
「Local CMOS Clock」は直感的に CMOS Clock(=RTC)と同期しているかのように見えますが、PC 起動時に RTC を参照した時刻を元にしたというだけで、動作中に RTC と協調,同期しているわけではないです。
Free-running System Clock
時刻サーバーと同期がとれなくて 24 時間以上経過したときの表示。
Free-running なので「同期する先のない」という意味だとおもってよいと思います。
そういうわけで表現は違いますが、ともに「時刻同期できていない」という点は共通です。
システムクロックと RTC の時刻を 1 分以上ずらします。
ずらすために timeadjx (http://www.monyo.com/technical/products/timeadjx/ ) というツールを使用します。
ダウンロードすると .\timeadjx-0.2\Release フォルダのに timeadjx.exe があるのでそれを使用します。
まずは、1 秒あたり 10 秒進めるために 1560000 (= 156000ns × 10) を設定します。
C>timeadjx set 1560000
SetSystemTimeAdjustment() 呼び出し中...
割込み発生時の加算時刻: 1560000 (100ns単位)
定期的な時刻調整 : 有効
自動的な時刻補正 : 無効
(自動的な時刻補正の詳細は、KB232488を参照してください)
実行するとものすごい勢い (1 秒で 10 秒分) で時刻が進むと思います。
6 秒以上経過したらデフォルトに戻します。
C>>timeadjx set 0
SetSystemTimeAdjustment() 呼び出し中...
割込み発生時の加算時刻: 0 (100ns単位)
定期的な時刻調整 : 無効
自動的な時刻補正 : 有効
(自動的な時刻補正の詳細は、KB232488を参照してください)
RTC の値を確認します。
RTC(ハードウェアクロック)の値を確認するために RWEverything (http://rweverything.com/ )というツールを使用します。
ダウンロードは RWportable~ というのを選択します。プラットフォームに応じて 32bit/64bit のいずれかをダウンロードします。
解凍すると RW.exe というのがあるのでそれを実行します。
実行すると、メニューから「Specific」→「IO Index/Data」→「CMOS - 70/71」を選択すると、CMOS のデータを表示します。
そうすると、RTC の時刻とシステムクロックの時刻がずれているのが確認できます。
RTC の方は、04 番地が時、02 番地が分、00 番地が秒になっています。
この例ではシステムクロックが 07:06:17 に対して RTC が 07:01:24 でシステムクロックが 5 分くらい進んでいます。
Address
00h
01h
02h
03h
04h
05h
06h
07h
08h
09h
Function
秒
分
時
日
月
年
Value(BCD)
24
01
07
19
07
20
しばらく放置します。
最大 1 時間くらい放置します。すると時刻が戻っていることに気付くはずです。
イベントビューアをみると、システムログのソース「Kernel-General」、イベント ID=1 が記録されているのが確認できます。
システムクロックが RTC に同期したこと、同期前と同期後の時刻が記録されています。
22:19:35 から 22:14:43 に変更になったと書いてありますが UTC での記録ですから、JST だと 07:19:35 から 07:14:43 に変更ということですね。
ふたたび RTC の値を確認します。
RTC の時刻とシステムクロックの時刻が一致しているのが確認できます。
この例ではシステムクロックと RTC がともに 07:20:14 となっていることが確認できます。
Address
00h
01h
02h
03h
04h
05h
06h
07h
08h
09h
Function
秒
分
時
日
月
年
Value(BCD)
14
20
07
19
07
20
tags: Windows で時刻あわせ posted in OS , Windows , 時刻 , 環境設定 by ooltcloud | 1 Comment
2020年7月25日
前回記事「Windows で時刻あわせ (4) w32tm (通信の確認)」はこちら 。
【注意と免責】
以下の内容は個人的な見解であり正しさを保証しません。正しさを必要とする場合は他のサイトの記事を参照してください。
w32tm は設定および時刻同期に失敗しやすいです。また失敗の原因が見えにくいこともリカバリーを難しくします。たとえば時刻 Client の設定をしていて時刻同期に失敗するとき、その原因が Client の設定ではなく Server 側の設定や挙動にある場合があります。
ここでは代表的なトラブルを上げてみます。
サーバーとクライアントの時刻の差が大きい
境界値は知りませんが、例えば時刻が日単位で異なると時刻は同期しません。
サーバーとクライアントの時刻の差が小さい
実は正しく同期できているのですが、観測者の視点から時刻サーバーとの時刻差が見えるために時刻同期されていないと誤認されることがあります。
デフォルトでは時刻差が 5 分以内の時に起こります。
この辺りの詳しい動作は「step 調整」と「slew 調整」という語を検索してみて下さい。
(slew 調整の意味が分からない場合は、w32tm を使用せず素直に桜時計を使いましょう。)
w32tm /resync コマンを実行したが同期しない(時刻サーバーとの間に時間差がある)
resync コマンドによって時刻を即同期するとは限りません。resync コマンドの help を見たらわかりますが、「今すぐ時刻の同期をとり直すようにコンピューターに指示します」と書かれています。つまり Windows time サービスに時刻の同期をとり直す "指示" を出すだけです。
windows time サービスは指示された結果、「今は時刻合わせしなくていい」とか「サーバーから取得した時刻は信頼できないからダメだ」などの判断をする可能性があり、その結果時刻同期しない可能性があります。
そもそも resync コマンドは「その場で step 調整するコマンド」ではありません。その点を勘違いしないようにしましょう。
通信できる状態であるはずなのに時刻設定しない
時刻サーバーと通信できていない(例えばファイアウォールに阻まれている)のは論外として、時刻サーバーと通信できているはずなのに時刻を同期しない場合があります。
考えられることとして、クライアントモードでアクセスしていない(対称モードでアクセスしている)可能性があります。
クライアントモードでアクセスするためには、ntp サーバーの指定の際に末尾に ",0x8" または ",0x9" を付加して指定します。付加しない場合、対称モードでのアクセスになります。(Win7 まで。Win2008R2,Win8 以降は無指定の場合クライアントモードになるようです。)
なぜ対称モードではだめなのか?についてはそういうものだと思ってください(汗
時刻を取得したが、時刻設定しない
参照先の時刻サーバーから時刻を取得しているはずなのに同期しないことがあります。
このような場合は、サーバーから取得した時刻が信頼できないものであった可能性があります。
たとえば以下のような要因があります。
Stratum(階層)の値がおかしい。
Stratum の値が 0 の場合、参照した時刻サーバーがさらに上位の時刻サーバーとの時刻同期に失敗しています。
また、Stratum の値が 15 の場合は、その時刻サーバーとの同期はできません。
leap indicator(閏インジケーター)が 3(時刻同期していない)になっている。
参照した時刻サーバーがさらに上位の時刻サーバーとの時刻同期に失敗しています。
Disparsion(ルート分散)の値が大きい。
時刻のゆらぎが大きいと時刻が信頼できないと判断されることがあります。
特に Windows の場合、同期する時刻サーバーがない場合、Disparsion の値は 10 秒で、この値だとクライアント側の w32tm は時刻が信頼できないと判断するようです。(多分。本当にそうであるかの検証は私はしていません。)
上記の状態は、参照先の時刻サーバーが windows である場合、その参照先の時刻サーバー側で w32tm /query /status コマンド (Windows Vista, Windows Server 2008 以降) による確認することができます。
たとえば以下の表示のようになっている時刻サーバーと同期しようとしても同期しません。なぜなら時刻サーバーが同期していないため時刻サーバーの時刻が信用できないからです。時刻サーバーとさらに上位の時刻サーバー間の通信が切断されていないかなどを確認してください。
C>w32tm /query /status
閏インジケーター: 3 (最後の 1 分間は 61 秒)
階層: 0 (未指定)
精度: -6 (ティックごとに 15.625ms)
ルート遅延: 0.0000000s
ルート分散: 10.0000000s
参照 ID: 0x00000000 (未指定)
最終正常同期時刻: 20xx/xx/xx xx:xx:xx
ソース: Free-running System Clock
ポーリング間隔: 10 (1024s)
マーカー部分は表現は違えど皆「時刻は同期していません(=時刻に信頼性がありません)」と言っています。
時刻を取得しようとしない(通信しない)
通信間隔が短い可能性があります。しばらく時間を置くか、通信先時刻サーバー(ピア)を変更してリトライするなどしてみてください。
w32tm /resync を行って「コマンドは正しく完了しました。」と表示されるが時刻同期しない。
「コマンドは正しく完了しました。」と表示されても、w32tm /query /status コマンドで階層(Stratum)が 0 になっているようだと時刻同期に失敗しています。前述のトラブル事例に該当するものがあるかどうかを確認してください。
時刻同期に失敗しているのになぜ「コマンドは正しく完了しました。」と表示されるかというと、文字どおり「コマンドは正しく完了し」たからです。どこにも「時刻同期に成功しました」と書かれていない点に注意しましょう。
時刻同期に成功したかどうかは w32tm /resync コマンドの表示ではなく、w32tm /query /status コマンドでソース(現在の時刻参照先サーバー)と階層(stratum)が正しい表示となっているかどうかで確認します。正しい表示とは、ソースが参照先の時刻サーバーになっていること、階層(Stratum)が参照先の時刻サーバーの値 + 1 となっていることです。
tags: Windows で時刻あわせ posted in OS , Windows , 時刻 , 環境設定 by ooltcloud | 1 Comment
2020年7月25日
前回記事「Windows で時刻あわせ (3) w32tm (Server 側)」はこちら 。
【注意と免責】
以下の内容は個人的な見解であり正しさを保証しません。正しさを必要とする場合は他のサイトの記事を参照してください。
w32tm の設定作業で同期に失敗すると、なにがおかしいのか目に見えないので途方に暮れてしまいます。
一応 w32tm /debug によるログ取得とかできますが、理解が難しいです。(多分)
そこで、桜時計に通信の相手方になってもらい、どのような通信をしているのかを確認する方法を紹介します。
時刻サーバーからの応答の確認。
同期したい時刻サーバー(下図では 192.168.0.1)に向けて桜時計を設定し、サーバーからの応答を確認します。
LI と Stratum を確認します。Dispersion は確認できません。
OK な例
LI(leap Indicator / 閏インジケータ)が 0, Stratum(階層)が 1 ~ 14 の間なので OK です。
NG な例
LI が 3, Stratum が 0 で、ともに時刻同期ができていないという意味なので NG です。
時刻クライアント側からの要求の確認
w32tm の manualpeerlist で指定する時刻サーバーのアドレスを桜時計を実行しているサーバーに向けます。
MODE1 は対称モード (Synmetric Active)、MODE3 はクライアントモードです。
MODE3 になっていれば OK です。
また前提として UDP 123 の通信がファイアウォールで阻まれていないことは事前に確認しておいてください。
w32tm /resync を実行しても桜時計に反応がない場合、ファイアウォール等で通信が阻害されている可能性があります。
とはいえ、w32tm /resync を実行してもパケットを送出しないケースもあるのでその点は注意です。(汗
間違いなく通信は通るはず…と思う場合は、ピア(=時刻サーバー)の IP アドレスを変えて試したり、w32tm /debug で記録されるログを確認するなどをしてみてください。
また、dispersion やその他詳細なデータも確認したい、というニーズがある場合は、NTP Monitor (https://www.satsignal.eu/software/net.htm ) とか良いかも知れませんので参考にしてみてください。
tags: Windows で時刻あわせ posted in OS , Windows , 時刻 , 環境設定 by ooltcloud | 1 Comment
2020年7月25日
前回記事「Windows で時刻あわせ (2) w32tm (Client 側)」はこちら 。
【注意と免責】
以下の内容は個人的な見解であり正しさを保証しません。正しさを必要とする場合は他のサイトの記事を参照してください。
時刻サーバーとして設定されているかどうかは、管理者権限のあるコマンドプロンプトで「w32tm /query /configuration」を実行することで確認できます。
C>w32tm /query /configuration
[構成]
----------------- (略) -----------------
[タイム プロバイダー]
NtpServer (ローカル)
DllName: C:\WINDOWS\system32\w32time.dll (ローカル)
Enabled: 1 (ポリシー)
InputProvider: 0 (ローカル)
AllowNonstandardModeCombinations: 1 (ローカル)
NtpClient (ローカル)
----------------- (略) -----------------
NtpServer ブロックの Enabled が 1 になっていれば OK です。
Enabled が 0 となっている場合は、グループポリシーの「コンピューターの構成→管理用テンプレート→システム→Windows タイムサービス→タイムプロバイダー」の「Windows NTP サーバーを有効にする」を「有効」にするか、レジストリ「\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer」にある Enabled を 1 にします。
しかし場合によっては以下の設定を追加で行う必要があるかもしれません。
w32tm /config /update /reliable:yes /LocalClockDispersion:0
/reliable:yes は stratum を 0, leap indicator を 3 にしないための指定、/LocalClockDispersion:0 は分散(時刻のゆらぎ)が全くない(=0 秒)とする指定です。
ちなみに「分散」は統計的な手法で求められてはいますが variance(=標準偏差を得る前の平方根を得る前の「分散」)ではなく dispersion なので日本語に惑わされないようにしましょう。(単位も s^2 じゃないからね?)
また Windows XP 系の場合、上記オプションがないため、レジストリを直接編集します。
場所は「\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time」の中にある以下の 3 つを変更します。
Config にある AnnounceFlags を 5 に(/reliable:yes に対応) 。LocalClockDispersion を 0 (/LocalClockDispersion:0 に対応) にします。
TimeProviders\NtpServer にある Enabled を 1 にします。(=Ntp Server として動作)
w32time サービスを再起動します。
net stop w32time
net start w32time
この設定は、時刻サーバーと上位の時刻サーバーとの通信が切断された場合に下位の時刻クライアントが同期しなくなることを防ぐために行います。逆に言うとこの設定を行わない場合、時刻サーバーと上位の時刻サーバーとの間に通信障害が起こると、この時刻サーバーを参照している「全ての」時刻クライアントが時刻同期しなくなる可能性があります。
つまりこの設定は、時刻を参照させたい Windows の時刻が信頼に足らないものであっても「信頼性の高い時刻サーバーである」と騙らせる設定です。これにより時刻クライアントが時刻サーバーと同期しやすくなりますが、反面時刻サーバーの時刻がおかしくても時刻クライアントはそれに気づけないため、時刻同期できていない状況よりも深刻な問題を引き起こす可能性があります。したがって、この設定を採用する場合は、その点を考慮し採用が妥当かどうかを慎重に検討してください。
tags: Windows で時刻あわせ posted in OS , Windows , 時刻 , 環境設定 by ooltcloud | 1 Comment
2020年7月25日
前回記事「Windows で時刻あわせ (1) 桜時計」はこちら 。
【注意と免責】
以下の内容は個人的な見解であり正しさを保証しません。正しさを必要とする場合は他のサイトの記事を参照してください。
桜時計ではダメなんだ・・・という場合。windows time サービス、または w32time サービス、あるいは w32tm という windows 標準の仕組み(以下「w32tm」という呼び方で統一)があるんだからそれでやりたい、と思うこともあるでしょう。
やめたほうがいいです(何
必要とする機能が桜時計の機能で十分なら、桜時計の使用が一番楽ができるし確実で直感的です。もし桜時計を使いたくない理由が「Windows 標準でないから」「フリーウェアを使うのはちょっと」といった機能以外の理由なら、その理由を退けて桜時計を使う選択をしたほうがおそらく幸せになれます(汗
それでも w32tm を使用するんだという場合、設定方法はグループポリシーを使用する方法と w32tm コマンドを使用する方法の2つがあります。
内容的には変わりませんが、両方設定された場合、グループポリシーの設定のほうが優先されます。
以下それぞれの手順を手短に紹介します。
グループポリシーを使用する方法
グループポリシーエディタを起動します。(例えば 'Win' キー + 'R' キー で「ファイル名を指定して実行」を表示し、そこへ 'gpedit.msc' を入力)
「ローカル コンピューター ポリシー」→「コンピューターの構成」→「管理テンプレート」→「システム」→「Windows タイム サービス」→「タイム プロバイダー」とたどります。
「Windows NTP クライアントを構成する」を選択し、以下を設定します。
「有効」を選択します。
「NtpServer」に「<NTP サーバー名>,0x9」を設定します。たとえば ntp.nict.jp の場合は「ntp.nict.jp,0x9」です。0x9 が何かは他のページで調べてください。おまじないです。(0x9 = 0x8 + 0x1 で、0x8 は client mode、0x1 は同期間隔(0x0 は自動調整, 0x1 は固定、です。)
「Type」は「NTP」を選択します。
「Windows NTP クライアントを有効にする」を選択し、以下を設定します。
w32tm コマンドを使用する方法
管理者権限でコマンドプロンプトを起動します。
以下のコマンドを入力します。
w32tm /config /update /manualPeerList:<NTP サーバー名>,0x9 /syncFromFlags:manual
例えば ntp サーバーが ntp.nict.jp の場合は以下のようになります。
w32tm /config /update /manualPeerList:ntp.nict.jp,0x9 /syncFromFlags:manual
確認方法
設定した ntp サーバー(ピア)の確認
コマンドプロンプトで「w32tm /query /peers」を実行します。(Windows Vista 以降。XP ではできません)
実行すると以下のように表示されます。「ピア」のところに設定した ntp サーバー名が表示されていれば成功です。設定と違うものが表示されている場合、より優先される設定が行われている場合があります。その場合はローカルグループポリシーやドメインのポリシーなどに設定がないかを確認します。
C>w32tm /query /peers
ピア数: 1
ピア: ntp.nict.jp,0x9
状態: 保留中
残り時間: 776.3186433s
モード: 0 (予約)
階層: 0 (未指定)
ピアポーリング間隔: 0 (未指定)
ホストポーリング間隔: 0 (未指定)
Windows XP など w32tm /query コマンドがない OS で設定した内容を確認したい場合、レジストリエディタを使用すると設定内容を確認できます。場所は \HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters の NtpServer などに記録されています。
また、グループポリシーで設定した値はここには記録されません。ここに記録されるのは w32tm コマンドで設定した内容だけです。
時刻同期の確認
管理者権限のコマンドプロンプトで「w32tm /resync」を実行します。
「コマンドは正しく完了しました。」と表示がでればとりあえず OK です。それ以外の場合は対策が必要です。(が、必ずしも問題は Client 側の設定ではないかもしれません。)
C>w32tm /resync
再同期コマンドをローカル コンピューターに送信しています。
コマンドは正しく完了しました。
「コマンドは正しく完了しました。」と表示された場合、w32tm /query /status を実行してみて、閏インジケーターが警告なし、階層が 0 以外、ソースが意図した ntp サーバー名になっていれば OK です。
C> w32tm /query /status
閏インジケーター: 0 (警告なし)
階層: 2 (二次参照 - (S)NTP で同期)
精度: -6 (ティックごとに 15.625ms)
ルート遅延: 0.0312500s
ルート分散: 7.7757688s
参照 ID: 0x0A545792 (IPv6 アドレスの MD5 ハッシュ値の部分: )
最終正常同期時刻: 20xx/xx/xx xx:xx:xx
ソース: ntp.nict.jp,0x9
ポーリング間隔: 6 (64s)
その他
Windows 7 以降の場合、Windows Time サービスが「自動(トリガー開始)」になっている場合があります。
この状態だと Windows Time サービスを起動してもすぐ停止してしまうので、管理者権限のコマンドプロンプトを起動して、以下のコマンドを実行し、トリガーを削除します。
sc triggerinfo w32time delete
実行後、サービス一覧をみて windows time サービスの「トリガー開始」の表示が消えていれば OK です。
tags: Windows で時刻あわせ posted in OS , Windows , 時刻 , 環境設定 by ooltcloud | 1 Comment
2020年7月25日
【注意と免責】
以下の内容は個人的な見解であり正しさを保証しません。正しさを必要とする場合は他のサイトの記事を参照してください。
Windows で時刻合わせをしたいと思った場合、一番簡単で直感的なのは「桜時計」を使って時刻同期をすることです。Windows 95 時代の古いアプリケーションですが Windows 10 でもしっかり動きます。vector などでダウンロードできます。(例: https://www.vector.co.jp/soft/win95/personal/se050672.html )
ダウンロードして中身をみると2つプログラムがありますが SW_NORAS.EXE のほうを使用します。
立ち上げて放置するとすぐに終了してしまうので、表示されている間に「常駐する」にチェックします。すると自動でウインドウを閉じなくなるので、おちついて設定できるようになります。
接続先のサーバーは ntp.nict.jp がおすすめです。デフォルトには入っていないので手入力します。
また福岡大学(fukuoka-u.ac.jp)の NTP サーバーは絶対に使ってはいけません。(理由はぐぐってください)
その他各設定の意味は README.TXT を参照してください。
また桜時計を時刻サーバー(ntp server)にすることもできます。その場合は「SNTP サーバーとして動作する」にチェックを入れればいいだけです・・・と言いたいところですが下図のように「BIND エラー」になる場合があります。
これは windows time サービスと競合しているためです。サービス画面 ('Win' キー + 'R' キー で「ファイル名を指定して実行」を表示し、そこへ 'services.msc' を入力) で windows time を停止/無効にするとエラーはでなくなります。(下図は停止/無効にする前の表示です。)
桜時計はおそらく、どんな ntp client や ntp server よりも同期が楽です。エラーになった場合も表示がでるので「エラーだ」ということが捉えやすくその点でもおススメです。
tags: Windows で時刻あわせ posted in OS , Windows , 時刻 , 環境設定 by ooltcloud | 1 Comment
2018年5月18日
諸般の事情 (Mercury DB のサービス終了 ) をきっかけに、こちらに移転しました。
移転元サイト (http://ooltcloud.azurewebsites.net/ ) は、既にサービス停止しています。
posted in 移転 by ooltcloud | No Comments
2018年2月25日
Tomcat を使ったサーブレットの作成および JSP の作成手順のメモ。
今回は IDE に頼らず自力でコンパイル,デプロイする場合の手順です。
Tomcat のインストール
前提条件
JDK はインストールされていて、かつ、java.exe および javac.exe (= %JAVA_HOME%\bin) への Path は通っているものとします。
Tomcat のダウンロード
https://tomcat.apache.org/download-90.cgi から Tomcat をダウンロードします。今回は 64-bit Windows の ZIP 版を選択します。
ダウンロードした ZIP の展開
ダウンロードした ZIP の内容を解凍し、今回は C:\apache-tomcat-9.0.5 に配置します。
Tomcat の起動
C:\apache-tomcat-9.0.5\bin にある startup.bat を実行します。
最終行に「Server startup in・・・」と表示されれば OK です。
Tomcat の起動確認
http://localhost:8080 にアクセスできることを確認します。
Hello サーブレットの作成
デプロイ先フォルダの作成
C:\apache-tomcat-9.0.5\webapps に helloweb フォルダを作成します。その下に WEB-INF フォルダ、さらにその下に classes フォルダを作成します。
サーブレットコードの作成
C:\apache-tomcat-9.0.5\webapps\helloweb\WEB-INF\classes フォルダに helloweb.java というテキストファイルを作成します。
helloweb.java をメモ帳などで開き、以下のコードを記述し保存します。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
@WebServlet("/index")
public class helloweb extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html; charset=UTF-8;");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<p>こんにちは Tomcat</p>");
out.println("</body></html>");
out.close();
}
}
コンパイル
コンパイルします。
C>cd C:\apache-tomcat-9.0.5\webapps\helloweb\WEB-INF\classes
C>set CP=C:\apache-tomcat-9.0.5\lib\servlet-api.jar
C>javac -cp %CP% helloweb.java
C>dir
ドライブ C のボリューム ラベルはありません
ボリューム シリアル番号は 0000-0000 です
C:\apache-tomcat-9.0.5\webapps\helloweb\WEB-INF\classes のディレクトリ
2018/02/23 00:12 <DIR> .
2018/02/23 00:12 <DIR> ..
2018/02/23 00:12 898 helloweb.class
2018/02/22 23:58 592 helloweb.java
2 個のファイル 1,490 バイト
2 個のディレクトリ 100,000,000,000 バイトの空き領域
デプロイ
コンパイルしたクラスファイルを Tomcat に読ませるために、Tomcat を再起動します。
shutdown.bat を実行後、再度 startup.bat を実行します。
作成したサーブレットの確認
http://localhost:8080/helloweb/index にアクセスします。
Hello JSP の作成
JSP コードの作成
C:\apache-tomcat-9.0.5\webapps\helloweb フォルダに top.jsp というテキストファイルを作成します。
top.jsp をメモ帳などで開き、以下のコードを記述し保存します。また今回はテキストファイルのエンコーディングを Shift JIS (=ANSI) で保存します。
<%@ page language="java" contentType="text/html; charset=UTF-8;" pageEncoding="Shift_Jis" %>
<html><body>
<% out.print("<h1>Hello JSP (tomcat)</h1>"); %>
<p>現在時刻は <%=new java.util.Date()%> です</p>
</body></html>
JSP の確認
http://localhost:8080/helloweb/top.jsp にアクセスします。
posted in Java , Program , WEB by ooltcloud | No Comments
2018年2月25日
WildFly を使ったサーブレットの作成および JSP の作成手順のメモ。
今回は IDE に頼らず自力でコンパイル,デプロイする場合の手順です。
WildFly のインストール
前提条件
JDK はインストールされていて、かつ、java.exe および javac.exe (= %JAVA_HOME%;bin) への Path は通っているものとします。
WildFly のダウンロード
http://wildfly.org/downloads/ から WildFly をダウンロードします。今回は 11.0.0.Final の Java EE7 Full & Web Distribution の ZIP 版を選択します。
ダウンロードした ZIP の展開
ダウンロードした ZIP の内容を解凍し、今回は C:\wildfly-11.0.0.Final に配置します。
WildFly の起動
C:\wildfly-11.0.0.Final\bin にある standalon.bat を実行します。
最終行に「WildFly・・・Started」と表示されれば OK です。
WildFly の起動確認
http://127.0.0.1:8080 にアクセスできることを確認します。
Hello サーブレットの作成
デプロイ先フォルダの作成
C:\wildfly-11.0.0.Final\standalone\deployments に helloweb.war フォルダを作成します。その下に WEB-INF フォルダ、さらにその下に classes フォルダを作成します。
サーブレットコードの作成
C:\wildfly-11.0.0.Final\standalone\deployments\helloweb.war\WEB-INF\classes フォルダに helloweb.java というテキストファイルを作成します。
helloweb.java をメモ帳などで開き、以下のコードを記述し保存します。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
@WebServlet("/index")
public class helloweb extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html; charset=UTF-8;");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<p>こんにちは WildFly</p>");
out.println("</body></html>");
out.close();
}
}
コンパイル
コンパイルします。
C>cd C:\wildfly-11.0.0.Final\standalone\deployments\helloweb.war\WEB-INF\classes
C>set CP=C:\wildfly-11.0.0.Final\modules\system\layers\base\javax\servlet\api\main\jboss-servlet-api_3.1_spec-1.0.0.Final.jar
C>javac -cp %CP% helloweb.java
C>dir
ドライブ C のボリューム ラベルはありません
ボリューム シリアル番号は 0000-0000 です
C:\wildfly-11.0.0.Final\standalone\deployments\helloweb.war\WEB-INF\classes の ディレクトリ
2018/02/22 22:17 <DIR> .
2018/02/22 22:17 <DIR> ..
2018/02/22 22:17 899 helloweb.class
2018/02/22 22:13 597 helloweb.java
2 個のファイル 1,496 バイト
2 個のディレクトリ 100,000,000,000 バイトの空き領域
C>
デプロイ
C:\wildfly-11.0.0.Final\standalone\deployments フォルダに helloweb.war.dodeploy という空ファイル(0バイトのテキストファイル)を作成します。
ファイル名が helloweb.war.deployed に変更されたらデプロイ完了です。
作成したサーブレットの確認
http://127.0.0.1:8080/helloweb/index にアクセスします。
Hello JSP の作成
JSP コードの作成
C:\wildfly-11.0.0.Final\standalone\deployments\helloweb.war フォルダに top.jsp というテキストファイルを作成します。
top.jsp をメモ帳などで開き、以下のコードを記述し保存します。また今回はテキストファイルのエンコーディングを Shift JIS (=ANSI) で保存します。
<%@ page language="java" contentType="text/html; charset=UTF-8;" pageEncoding="Shift_Jis" %>
<html><body>
<% out.print("<h1>Hello JSP</h1>"); %>
<p>現在時刻は <%=new java.util.Date()%> です</p>
</body></html>
JSP の確認
http://127.0.0.1:8080/helloweb/top.jsp にアクセスします。
posted in Java , Program , WEB by ooltcloud | No Comments
2018年2月13日
テストなとで Hinemos Agent の接続先 Manger を変更したい場合があったのでその時の手順のメモ。
公式の資料があるかもしれないけど以下の内容はそれを見て書いていません。なのでそのような文書が存在するようであれば正式にはそちらを参照ください(汗
Hinemos Agent の設定ファイルは C:\Program Files (x86)\Hinemos\Agent6.0.0\conf フォルダにあります。
Agent.properties の変更
Agent.properties を管理者で実行したメモ帳で開き、最下行に
managerAddress=http://192.168.0.101:8081/HinemosWS/
という設定があるので、このアドレスを変更したい manager のアドレスに変更します。ポート番号が 8081 とあるのは間違いではないのでそのままにしておきます。
log4j.properties の変更
必要なのかどうか分かりませんが log4j.properties の変更をします。
log4j.properties 管理者で実行したメモ帳で開き、やはり最下行に
log4j.appender.syslog.SyslogHost=192.168.0.101
という設定があるので、同様にアドレスを変更します。
ただ、最下行の一つ前の行の改行コードが CR-LF ではなく LF だけになっているようで、メモ帳だと最終行とその一つ前の行がくっついて一行に見えてしまう点には注意します。
LF を改行として認識してくれるエディタの場合
メモ帳(改行 LF を改行として認識しないエディタ)の場合
編集上の注意点
メモ帳以外の、例えば LF を改行として認識できるエディタを安易に使用すると、場合によってはバーチャルストア上に変更が記録されてしまい、設定を変更したはずなのに(エディタで表示すると間違いなく変更されているのに)Hinemos Manager がその設定を認識しない、ということがあります。
その場合、例えば以下のフォルダに変更内容が記録されています。(ログオンユーザーが user01 の場合の例)
C>dir "%LOCALAPPDATA%\VirtualStore\Program Files (x86)\Hinemos\Agent6.0.0\conf"
ドライブ C のボリューム ラベルがありません。
ボリューム シリアル番号は 0000-0000 です
C:\Users\user01\AppData\Local\VirtualStore\Program Files (x86)\Hinemos\Agent6.0.0\conf のディレクトリ
2018/01/01 00:00 <DIR> .
2018/01/01 00:00 <DIR> ..
2018/01/01 00:00 6,531 Agent.properties
2018/01/01 00:00 1,491 log4j.properties
2 個のファイル 8,022 バイト
2 個のディレクトリ 100,000,000,000 バイトの空き領域
このフォルダに記録されているようであれば NG です。とりあえずこのフォルダのファイルは削除しましょう。
またこの挙動が良くわからない人は、このような事態を避けるためにはメモ帳で編集したほうが無難です。
設定の反映
設定変更後、Hinemos Agent サービスを停止してから C:\Program Files (x86)\Hinemos\Agent6.0.0\bin にある UnregistAgentService.bat と RegistAgentService.bat を順に実行すれば OK です。(管理者のコマンドプロンプトで実行します)
変更後の動作の確認
Hinemos Agent サービスの起動を確認します。起動されていなければ手動で起動します。
対象の Hinemos Manager の、リポジトリパースペクティブの "リポジトリ[エージェント]" ウインドウで対象ノードが表示されていれば OK です。
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2018年2月9日
javapath とか JAVA_HOME が分からなかったので調べた結果をメモ。以下が当たっているのかどうかは不明なので信用しないでください。
javapath
javapath というのは jre8 あたりから使用されている パブリック JRE のホスト先へのリンク(?)らしいです。
パブリック JRE については 「プライベートJREとパブリックJRE」 を参照してください。
具体的な場所は C:\ProgramData\Oracle\Java\javapath です。ここに java.exe, javaw.exe, javaws.exe が配置されます。
したがって、PATH 環境変数に C:\ProgramData\Oracle\Java\javapath を追加しておけば、update で JRE のインストールフォルダが変更されても、それを意識することなく java.exe などを実行することができます。(PATH 環境変数への C:\ProgramData\Oracle\Java\javapath の追加は JRE のインストーラーがしてくれるようです。)
ただ使用する場合は意識しなくていいですが、C:\ProgramData\Oracle\Java\javapath に java.exe などをホストする方法が前期の JRE8 と後期の JRE8 以降とで異なるようです。
前期の JRE8 は javapath フォルダに java.exe などのシンボリックリンクを配置していました。(以下は JRE8 Update 45 の例)
C:\ProgramData\Oracle\Java\javapath>dir
ドライブ C のボリューム ラベルがありません。
ボリューム シリアル番号は 0000-0000 です
C:\ProgramData\Oracle\Java\javapath のディレクトリ
2017/11/20 23:11 <DIR> .
2017/11/20 23:11 <DIR> ..
2017/11/20 23:11 <SYMLINK> java.exe [C:\Program Files\Java\jre1.8.0_45\bin\java.exe]
2017/11/20 23:11 <SYMLINK> javaw.exe [C:\Program Files\Java\jre1.8.0_45\bin\javaw.exe]
2017/11/20 23:11 <SYMLINK> javaws.exe [C:\Program Files\Java\jre1.8.0_45\bin\javaws.exe]
3 個のファイル 0 バイト
2 個のディレクトリ 10,000,000,000 バイトの空き領域
後期の JRE8 からは javapath_target_xxxxxxxxx フォルダに java.exe をコピーしたうえで、javapath_target_xxxxxxxxx へのジャンクションを張るようです。(以下は JRE9 の例)
C:\ProgramData\Oracle\Java>dir
ドライブ C のボリューム ラベルがありません。
ボリューム シリアル番号は 0000-0000 です
C:\ProgramData\Oracle\Java のディレクトリ
2018/01/17 20:08 <DIR> .
2018/01/17 20:08 <DIR> ..
2018/01/17 20:44 <DIR> .oracle_jre_usage
2018/01/17 20:04 <DIR> installcache_x64
2018/01/17 20:04 <JUNCTION> javapath [C:\ProgramData\Oracle\Java\javapath_target_162006234]
2018/01/17 20:04 <DIR> javapath_target_162006234
0 個のファイル 0 バイト
6 個のディレクトリ 10,000,000,000 バイトの空き領域
C:\ProgramData\Oracle\Java>dir javapath
ドライブ C のボリューム ラベルがありません。
ボリューム シリアル番号は 0000-0000 です
C:\ProgramData\Oracle\Java\javapath のディレクトリ
2018/01/17 20:04 <DIR> .
2018/01/17 20:04 <DIR> ..
2018/01/17 20:04 231,488 java.exe
2018/01/17 20:04 232,000 javaw.exe
2018/01/17 20:04 335,424 javaws.exe
3 個のファイル 798,912 バイト
2 個のディレクトリ 10,000,000,000 バイトの空き領域
JRE7 以前は javapath に相当するフォルダは %SystemRoot%\System32 で、そこに パブリック JRE の java.exe 等をコピーしていたようです。(未確認)
ところで javapath には java.exe とかしかないけど、そこからどうやって jvm.dll とかを探しているんですか?って話については、自身(java.exe とか) のバージョンをキーにしてレジストリを参照しているんじゃないですかね?多分。しらんけど(汗
JAVA_HOME
JAVA_HOME とは JAVA アプリケーションがランタイムの場所を知るために使う環境変数らしいです。
転じて使用する JRE を切り替えるために使われたりするようです。
例えば C:\Program Files\Java\jdk1.8.0_161 にあるランタイムを使用したい場合は、JAVA_HOME 環境変数に C:\Program Files\Java\jdk1.8.0_161 を設定します。
JAVA_HOME 環境変数が設定されていれば、アプリケーションは %JAVA_HOME%\bin\java.exe -jar myApp.jar のように実行すればいいということですね。
ただ JAVA_HOME の設定だけだとコマンドプロンプトから実行時に上記のように JAVA_HOME も記述しないとならず煩わしいので、併せて PATH 環境変数に %JAVA_HOME%\bin; を設定することが多いようです。
また JAVA_HOME の設定は JRE や JDK のインストーラーが自動で設定しないので、必要であれば手動で設定する必要があります。
posted in Java , OS , Program , Windows , 環境設定 , 開発環境 by ooltcloud | No Comments
2018年2月5日
時折、Hinemos がインターナルエラーを記録していることがあります。
多分、Hinemos Manger をホストしているサーバーの時刻が意図している時刻と異なるので再確認してみてください。
[root@localhost ~]# date
2018年 2月 5日 月曜日 05:07:12 JST ←この時刻は意図している時刻ですか?
posted in Hinemos , サーバー管理 by ooltcloud | No Comments
2018年2月5日
監視対象ノードで Hinemos Agent Service が起動していることを確認します。
イベントログの監視は Hinemos Agent を経由した監視なので Hinemos Agent Service が起動している必要があります。
「EVENT FOR TRAP」の設定を変更します。
「EVENT FOR TRAP」の設定を SNMP TRAP 監視の場合と同様にしておきます。
設定内容は [鯖缶] hinemos 6 で Windows の SNMP Trap を監視 の 2 項を参照してください。
Windows イベント監視の設定をします。
「監視設定パースペクティブ」の”監視設定[一覧]” ウインドウで「Windows イベント監視」を作成します。
今回は Application ログに記録するイベントソース EventTest の ID = 1 を監視することにします。
Powershell を管理者として実行し テスト用のイベントソース (EventTest) を作成します。
New-EventLog -LogName Application -Source EventTest
Powershell からイベントを書き込みます。
Write-EventLog -LogName Application -Source EventTest -EventId 1 -EntryType Information -Message "イベント01"
記録されることを確認します。
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2018年2月1日
標準的に用意されている Trap は以下らしいです。
(ただし Windows が以下の全ての OID を Trap 送信するかどうかは確認していません)
OID
内容
.1.3.6.1.6.3.1.1.5.1
Cold Start
.1.3.6.1.6.3.1.1.5.2
Warm Start
.1.3.6.1.6.3.1.1.5.3
Link Down
.1.3.6.1.6.3.1.1.5.4
Link Up
.1.3.6.1.6.3.1.1.5.5
Authentication Failure
設定は以下な感じで行います。
監視対象ノード (Windows) の SNMP Service の実行中を確認します。
SNMP Service が実行していることを確認します。また SNMP Service の「トラップ」タブを確認し、トラップ送信先の設定が Hinemos Manager に向いていることを確認します。(以下の画像の例だと 192.168.0.101 が Hinemos Manager)
また SNMP TRAP Service の起動は必要ありません。(これはその Windows が SNMP Trap を受信するためのサービスなので。多分)
TRAP 受信するたびにイベント通知するように「EVENT FOR TRAP」の設定を変更します。
「監視設定パースペクティブ」の"監視設定[通知]" ウインドウで「EVENT FOR TRAP」の設定をクリックします。
「EVENT FOR TRAP」の設定を以下のように設定します。
具体的には「重要度変化後の二回目以降の通知」を「常に通知する」に変更します。
SNMPTRAP 監視の設定を変更します。
「監視設定パースペクティブ」の"監視設定[一覧]" ウインドウで、既定で設定されている監視項目 ID「SNMPTRAP_DEFAULT」をクリックし以下のように変更します。
具体的には、コミュニティ名は未指定のままとし「未指定のトラップ受信時に通知する」にはチェックを入れます。(とりあえず来るものは全て受け入れということで ^^;)
また、通知に「EVENT FOR TRAP」を選択します。
監視対象ノードを再起動し、テストを行います。
例えば結果はこんな感じで記録されます。(Windows の起動時)
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | 1 Comment
2018年1月31日
リソース監視の設定は監視項目をプルダウンから選ぶだけです。
リソース値は SNMP 経由で取得するため、監視対象ノードで SNMP サービスが起動している必要があります。またファイアウォールの設定も忘れずに行っておきます。(プロセス監視等と同様です。ファイアウォールの設定や SNMP サービス等の設定は「[鯖缶] Hinemos 6 agent for windows のインストール 」を参照してください。)
その他、リソース監視に関する注意事項等は以下。
リソース値と OID の対応について
監視項目とアクセス先の OID の対応は以下のようです。
(snmpwalk の結果から推測しただけなので違うかもしれません。)
Hinemos agent をインストールしなくても監視可能な項目
監視項目
アクセス先の OID
CPUコア別使用率
.1.3.6.1.2.1.25.3.3.1.2
ファイルシステム使用率
.1.3.6.1.2.1.25.2.3.1
パケット数
エラーパケット数
ネットワーク情報量
.1.3.6.1.2.1.2.2.1
監視するために Hinemos agent のインストールが必要な項目
監視項目
アクセス先の OID
CPU使用率
スワップI/O
インタラプトレート
コンテキストスイッチ
.1.3.6.1.4.1.2021.11
メモリ使用率
.1.3.6.1.4.1.2021.4
ディスクI/O回数
ディスクI/O量
.1.3.6.1.4.1.2021.13.15
大容量ファイルシステム使用率
.1.3.6.1.4.1.2021.9.1
大きく分けて MIB-2 (.1.3.6.1.2.1) を参照する項目と Enterprise.2021 (.1.3.6.1.4.1.2021) を参照する項目とがあります。前者が Windows の SNMP が標準で返す値、後者が Hinemos agent をインストールすることで組み込まれる SNMP 拡張エージェントが返す値です。
前者は Hinemos agent をインストールしなくても取得できます。
後者は Hinemos agent のインストールが必要です。しかし Hinemos agent がインストールされていれば Hinemos agent サービスが停止していても取得できます。(SNMP サービスは起動している必要はありますが。)
似た名称のリソース値について
監視項目に「CPUコア別使用率」と「CPU使用率」、「ファイルシステム使用率」と「大容量ファイルシステム使用率」と似た名称のものがあります。これらの違いは以下です。
「CPUコア別使用率」と「CPU使用率」
「コア別」か「全体」かの違いです。
「ファイルシステム使用率」と「大容量ファイルシステム使用率」
「ファイルシステム使用率」は SNMP から ディスク容量 (byte) と使用量 (Byte) を取得し、Hinemos manager が使用率 (%) を計算します。このためボリュームの容量が 2TB (多分。Int32 値なので) を超える場合オーバーフローしてしまうため計算できません。「大容量ファイルシステム使用率」は SNMP エージェント側で使用率 (%) を計算するので 2TB 以上のボリュームでも使用率を得ることができます。
したがって、ボリューム容量が 2TB 以下で hinemos agent をインストールしない場合以外は「ファイルシステム使用率」を選択するメリットはないため、常に「大容量ファイルシステム使用率」をを選択すればよいと思います。
拡張エージェントの MIB の内容について
Enterprise.2021 に snmpwalk でアクセスしてみると以下の出力が得られます。
つまり以下に列挙されているリソース値が Hinemos の SNMP 拡張エージェントによる出力です。
# Drive は A: FDD, C: HDD, Q: CD-ROM があると仮定しています。
# 取得値はすべて 0 にしています。
# 緑色のマーク箇所および空行は見やすくするために加工しています。
snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.4.1.2021
-- .1.3.6.1.4.1.2021.4
UCD-SNMP-MIB::memTotalSwap.0 = INTEGER: 0 kB
UCD-SNMP-MIB::memAvailSwap.0 = INTEGER: 0 kB
UCD-SNMP-MIB::memTotalReal.0 = INTEGER: 0 kB
UCD-SNMP-MIB::memAvailReal.0 = INTEGER: 0 kB
UCD-SNMP-MIB::memTotalFree.0 = INTEGER: 0 kB
UCD-SNMP-MIB::memBuffer.0 = INTEGER: 0 kB
UCD-SNMP-MIB::memCached.0 = INTEGER: 0 kB
-- .1.3.6.1.4.1.2021.9.1
UCD-SNMP-MIB::dskPath.1 = STRING: A:\\
UCD-SNMP-MIB::dskPath.3 = STRING: C:\\
UCD-SNMP-MIB::dskPath.18 = STRING: Q:\\
UCD-SNMP-MIB::dskPercent.1 = INTEGER: -1
UCD-SNMP-MIB::dskPercent.3 = INTEGER: 0
UCD-SNMP-MIB::dskPercent.18 = INTEGER: 0
-- .1.3.6.1.4.1.2021.11
UCD-SNMP-MIB::ssSwapIn.0 = INTEGER: 0 kB
UCD-SNMP-MIB::ssSwapOut.0 = INTEGER: 0 kB
UCD-SNMP-MIB::ssCpuRawUser.0 = Counter32: 0
UCD-SNMP-MIB::ssCpuRawNice.0 = Counter32: 0
UCD-SNMP-MIB::ssCpuRawSystem.0 = Counter32: 0
UCD-SNMP-MIB::ssCpuRawIdle.0 = Counter32: 0
UCD-SNMP-MIB::ssCpuRawWait.0 = Counter32: 0
UCD-SNMP-MIB::ssCpuRawKernel.0 = Counter32: 0
UCD-SNMP-MIB::ssCpuRawInterrupt.0 = Counter32: 0
UCD-SNMP-MIB::ssRawInterrupts.0 = Counter32: 0
UCD-SNMP-MIB::ssRawContexts.0 = Counter32: 0
-- .1.3.6.1.4.1.2021.13.15
UCD-DISKIO-MIB::diskIOIndex.1 = INTEGER: 1
UCD-DISKIO-MIB::diskIOIndex.3 = INTEGER: 3
UCD-DISKIO-MIB::diskIOIndex.17 = INTEGER: 17
UCD-DISKIO-MIB::diskIODevice.1 = STRING: A
UCD-DISKIO-MIB::diskIODevice.3 = STRING: C
UCD-DISKIO-MIB::diskIODevice.17 = STRING: Q
UCD-DISKIO-MIB::diskIONRead.1 = Counter32: 0
UCD-DISKIO-MIB::diskIONRead.3 = Counter32: 0
UCD-DISKIO-MIB::diskIONRead.17 = Counter32: 0
UCD-DISKIO-MIB::diskIONWritten.1 = Counter32: 0
UCD-DISKIO-MIB::diskIONWritten.3 = Counter32: 0
UCD-DISKIO-MIB::diskIONWritten.17 = Counter32: 0
UCD-DISKIO-MIB::diskIOReads.1 = Counter32: 0
UCD-DISKIO-MIB::diskIOReads.3 = Counter32: 0
UCD-DISKIO-MIB::diskIOReads.17 = Counter32: 0
UCD-DISKIO-MIB::diskIOWrites.1 = Counter32: 0
UCD-DISKIO-MIB::diskIOWrites.3 = Counter32: 0
UCD-DISKIO-MIB::diskIOWrites.17 = Counter32: 0
-- EOF?
UCD-DISKIO-MIB::diskIOWrites.17 = No more variables left in this MIB View (It is past the end of the MIB tree)
しかし Hinemos の拡張エージェントが NET-SNMP の持ち物である Enterprise.2021 を実装してしまうのはどうなのかな?という気は若干します。
Linux と Windows とで アクセス先 (=OID) を同じにすることで OS を差異をなくし、Manager は監視対象ノードの OS を意識せずアクセスできるようになるというのは理解できるのですが、行儀がわるい実装な気がしますね・・・(汗
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2018年1月23日
Windows に対する SNMP 監視やプロセス監視は ASCII 以外の文字が通らないという話を「[鯖缶] Hinemos 6 で windows のプロセスを監視 」と「[鯖缶] hinemos 6 の文字化けについて 」で書きました。(もしかしたら上手く通す方法はあるのかもしれませんが)
「いやでも、どうしても ASCII 以外の文字を Windows から拾わないと」という場合は Hinemos agent を介したカスタム監視をするより他にありません。
ということでカスタム監視を試してみます。
プロセス監視の代わりのカスタム監視を考えてみます。
以下がその手順です。
監視対象ノードで Hinemos agent が動作していることを確認します。
監視対象の Windows で hinemos agent サービスが動作していることを確認します。
また、リポジトリパースペクティブの "リポジトリ[エージェント]" ウインドウに監視対象ノードが表示されていることを確認します。(Windows 側で hinemos agent サービスが動作していても、"リポジトリ[エージェント]" ウインドウに表示されていない場合は動作しません。)
監視設定パースペクティブの "監視設定[一覧]" でカスタム監視(数値)を選択します。
以下の項目を画面の通りに設定します。
監視項目 ID
スコープ
間隔
監視
通知ID
アプリケーション
コマンドを設定します。
コマンドを以下のように設定します。
powershell -command "$m = (Get-WmiObject win32_process | ? {$_.name -match 'notepad'}).CommandLine | ? {$_ -match '新しい'}; 'value,{0}' -f $m.count"
上記はコマンド欄が一行でしか書けないのでワンライナーで書いていますが、以下の Powershell スクリプト相当のことを行っています。
# wmi 経由でプロセス情報を取得する
$a = Get-WmiObject Win32_Process
# プロセス名に 'notepad' が含まれるものを抽出する
$b = $a |
? {
$_.name -match 'notepad'
}
# さらにコマンドラインに '新しい' が含まれるものを抽出する
$m = $b.CommandLine |
? {
$_ -match '新しい'
}
# 結果(プロセス数)を key,value の形式で出力する
'value,{0}' -f $m.count
このスクリプトをワンライナーに書き換えて、Powershell.exe の -command オプションに渡しています。
また win32_process の CommandLine の値はプロセス名と引数が分かれずに一つの文字列として得られます。
たとえば以下のようにで戻ってきます。
"C:\WINDOWS\system32\notepad.exe" "C:\Users\user01\Desktop\新しいテキスト ドキュメント.txt"
従ってこの点は SNMP を使った標準のプロセス監視と正規表現の表現方法が異なるので注意します。
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2018年1月21日
さて次は Himeos でリソース監視を…と思ってダイアログを開くとこんな表示がありました。
なにやら文字が化けています。
よく見るとリポジトリの登録状況がこんな・・・
原因はノードの作成時に情報を SNMP 経由で取得しているのですが、その際にデバイス名が ASCII 文字以外の文字が使われてたからです。(今回の場合は「仮想イーサネットアダプター」)
どうして?の前に、先に結論(汗
Windows に対して SNMP で取得した文字列は文字化けします。具体的には、ノード登録時の SNMP による探索、SNMP 監視、プロセス監視が該当です。
対策
ノードの登録情報は化けている部分を手入力で修正することで対応します。
SNMP 監視とプロセス監視は対策はありません。非 ASCII 文字が監視対象にならないように注意します。どうしても何とかしたい場合にはカスタム監視を検討します。
原因
なぜ文字化けが起こるかというと hinemos では SNMP でデータを取得する際のエンコードは UTF-8 固定でしか取得しないからです。対して Windows の SNMP は Shift-JIS で応答します。この結果文字化けが発生します。
従って SNMP でデータを取得する SNMP 監視はもちろんのこと、SNMP 経由で情報を取得するリポジトリへのノードの作成/変更やプロセス監視も影響を受けます。SNMP Trap 監視だけは文字コードが指定できるので大丈夫です(多分)
確認
本当にそうであるのかどうかを確認してみます。ソースコードは https://github.com/hinemos/hinemos/find/master で公開されています。以下の引用は 2017/1/15~20 頃にしていますので多分 version 6.0.* あたりのコードです。
まずプロセス監視のコードを確認してみます。なぜかというとプロセス監視では以下の理由で Linux 系と Windows で処理が異なると予想されるからです。
プロセス監視は SNMP 経由で情報を取得します。例えば Path を取得するために OID = .1.3.6.1.2.1.25.4.2.1.4 をアクセスします。このとき Linux 系はファイル名を含めて戻しますが (例: HOST-RESOURCES-MIB::hrSWRunPath.1 = STRING: "/usr/lib/systemd/systemd")、Windows は ディレクトリ名まででファイル名を戻しません。(例: HOST-RESOURCES-MIB::hrSWRunPath.388 = STRING: "C:\\WINDOWS\\system32\\") 従って Linux の OID = .1.3.6.1.2.1.25.4.2.1.4 の内容(ディレクトリ名+ファイル名)の内容に合わせたいと考えたなら Windows では OID = .1.3.6.1.2.1.25.4.2.1.4(ディレクトリ名)に加えて OID = .1.3.6.1.2.1.25.4.2.1.5 (ファイル名)を取得して連結する必要があります。
これを hinemos では RunMonitorProcess.java で実施していると思われます。該当部分は以下です。
// Windowsの場合を考慮して、valueCommandとvalueNameを連結する
if (command.length() == 0) {
// パスが取得できない場合はコマンド名
// パスがnull OR 空文字
command = name;
} else if (!command.startsWith("/")
&& command.endsWith("\\")
&& !command.equals(name)) {
// 条件・・・・
// パスが'/'以外の文字で始まり
// パスが'\'で終わっていて
// パスとコマンド名が違う
command = command + name;
}
このコードで分かることは Linux 系か Windows かの判定は、ノードの情報(プラットフォームや OS 名)や監視設定で設定するスコープなどを見ているのではなく SNMP で取得した値を元に判断しているということです。つまり文字コードは意識していない可能性が高いということです。なぜならば Windows の時だけ文字コードの変換を行っているところがあるならそこで command = command + name; を行えばよく「/ で始まらず \ で終わる」のような条件で分岐する必要がないからです。(*1)
また、この command や name に入る文字列を作っているのは Snmp4jPollerImpl.java であろうかと思います。以下に該当部分のコードを引用します。
case SMIConstants.SYNTAX_OCTET_STRING:
OctetString octStr = (OctetString) variable;
StringBuilder value = new StringBuilder();
byte[] bytes = octStr.getValue();
・・・・・
} else {
// WindowsのNIC名には0x00が含まれることがあるので除外する
int length = bytes.length;
for (int i = 0; i < bytes.length; i++) {
if (bytes[i] == 0x00) {
length = i;
break;
}
}
value.append(new String(bytes, 0, length) );
}
byte[] bytes = octStr.getValue(); で SNMP を経由してバイトストリームを取得しています。
バイトストリームを取得してから後は Windows を考慮してバイトストリーム中に 0x00 が含まれていた場合そこで打ち切る処理がありますが、それ以外にバイトストリームを操作する処理はありません。最終的に new String(bytes, 0, length) でバイトストリームを文字列に変換しています。このコンストラクタを使う場合、文字コードはプラットフォームデフォルトです。(*2)
というような状況であるため、Windows から SNMP 経由で ASCII 文字以外を取得するのはおそらく絶望的です。(*3)
この問題は実際に発生するか?
恐らく SNMP 経由で ASCII 以外の文字列を取得するケースはほぼないと思います。
リポジトリの登録情報は手修正で回避できますし、SNMP 監視で監視するデータで ASCII 以外が必要になることはほぼないかと思います。
もっとも顕在化の可能性がありそうなのはプロセス監視ですが、プロセス名や引数にしたところで ASCII 以外の文字を使うことはほぼないと思われる) ので、この問題が実際に顕在化することはあまりないのではないかと思います。
(*1)
このつくりは賛否両論ありそうです。
利点は他の設定値等を使用せずに取得した値のみで解決できることです。従って Windows なのか Linux なのかを指定しなくてもうまく対処することができます。
欠点は想定外のケースに対応できないことです。今回の場合は後者が顕在化してしまい上手くいかないケースだと思います。つまり SNMP が返す文字列の違いだけではなく文字コードも違うという点は想定に入ってない (仕様に含めていない) ということです。
かといって文字コードを違いを想定に追加するとした場合、現在のコードでは値をみるときには既にバイトストリームはデコードされた後ですから再デコードできませんし、仮にあらためてバイトストリームから再度デコードするとしても「Windows だったら絶対に Shift-JIS でしか戻らない」をハードコードしてしまうことになります。そうすると結局は柔軟性を失わせる結果になってしまいます。
ここは SNMP TRAP 監視がそうしているように、SNMP 監視やプロセス監視に対しても文字コードの指定が行えるようにしたほうがよりよかった気はします。
もちろん文字コードの指定だけだと内部的に command + name しているのはいいのか?という問題は残ったままになりますから、文字コードの指定ができれば全て解決というわけでもありません。その点ではプロセス監視については文字コードの指定ではなく OS の指定ができるようにしたほうがより良い気がします。
なぜならば OS に依存しないコードにしようとした結果、データから OS を類推しそれによって OS に依存した処理を書いており、結局は OS 依存のコードを埋め込んでしまっているからです。それよりはプロセス監視設定に OS の項目を入れてそれにより分岐したほうがスマートである気がします。
(*2)
https://docs.oracle.com/javase/jp/6/api/java/lang/String.html#String(byte[], int, int)
(*3)
システムの文字コードを ja_JP.UTF-8 から ja_jp.shift_jis に代えます?それはそれで非現実的な気がします。
仮にそうして Windows が OK になったとても UTF-8 な Linux で通らなくなりそうですし。
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2018年1月19日
posted in Excel , Office , Visio by ooltcloud | No Comments
2018年1月17日
以下は Shift JIS と UTF-8 の文字コード不一致について確認する方法です。
例えば送信元の文字列を以下のように設定します。
縺ゅ@.txt
これを受信側が上記の通り表示すれば文字コードは一致しています。しかし以下のように表示したら、送信側は Shift JIS で渡し受信側は UTF-8 で受けています。
あし.txt
同じように送信側の設定を「あし.txt」とし受信側で「縺ゅ@.txt」で表示されるなら、送信側は UTF-8 で渡し受信側は Shift JIS で受けています。
バイナリにすれば共に E3-81-82-e3-81-97 (%e3%81%82%e3%81%97) です。
posted in 情報技術 , 文字 by ooltcloud | No Comments
2018年1月15日
この記事 (http://ooltcloud.sakura.ne.jp/blog/201801/article_06231953.html ) の続きです。
以下はこの記事で作成したリポジトリの登録を前提としています。
プロセス監視の設定にあたって 2 つ重要な点があります。
プロセスの設定は正規表現で記述するのですが、これがマッチしないことがある。
たとえばメモ帳の起動(notepad.exe)を確認したい場合、"notepad" ではなく ".*notepad.*" のように書く必要があります。
したがってどのようなコマンドラインが渡り、それをマッチする正規表現は何かを事前にテストしたうえで入力したほうが確実です。(詳細は 「プロセス監視の対象となるコマンドライン引数について」 へ)
プロセスを起動/停止してもそれを SNMP で検知するまでにかなりの時間がかかる。
Windows の場合、手持ちの環境で実測したところ MIB の更新が 2 分周期のようでした。
したがって Hinemos で 1 分周期の設定にしていても、最遅の場合 3分 (=2分 + 1分) しないと Himemos には伝わらないことになります。加えて、同じ重要度の監視結果が複数回発生しないと通知しないことにしていると(=“監視設定[通知]” の設定) さらにその分遅れます。
なのでテストをする場合は、実際のプロセスの起動/停止からかなりの遅延が発生することを意識して行う必要があります。
特にこの 2 つがあわさると、確認に時間ばかりかかりいつまでたっても意図した結果が得られないというループに入ることがあるので要注意です(汗
以下は監視対象ノード (Windows) で hosts ファイルを開いたメモ帳が起動しているかどうかを確認する場合の設定手順です。
手順
Hinemos リポジトリの監視対象ノードの SNMP 設定を確認します。
リポジトリパースペクティブの “リポジトリ[ノード]” ウインドウで監視対象ノードをクリックし SNMP の設定を確認します。
コミュニティ名やバージョンが意図したとおりであれば OK です。
監視対象ノードの SNMP サービスの起動を確認します。
プロセス監視は Hinemos エージェントのインストールは不要ですが SNMP を介して情報を取得するので、SNMP サービスが起動している必要があります。
コミュニティ名を確認します。
コミュニティ名が意図したものであることも忘れずに確認しておきます。
監視設定を作成します。
監視設定パースペクティブの “監視設定[一覧]” ウインドウで「作成」を選択します。
プロセス監視を選択します。
プロセス監視の内容を設定します。
コマンドに以下を設定します。
^(|.*\\)notepad\.exe$
引数に以下を設定します。
^( |.*\\)*hosts *$
「大文字・小文字を区別しない」にチェックを入れます。
また、以下の項目も画面の通りに設定します。
監視項目 ID
スコープ
間隔
監視
通知ID
アプリケーション
監視の確認をします。
最初はメモ帳を起動していないので「危険」が記録されます。
メモ帳を起動します。
名前を指定して実行で「notepad c:\windows\system32\drivers\etc\hosts」と入力するなどして、host ファイルを表示させます。
3~5 分程度の後「情報」と記録されることを確認します。
プロセス監視の対象となるコマンドライン引数について
上記手順で「コマンド」と「引数」を設定しました。
ところがこの比較元になる SNMP から取得される文字列は想像と違うかもしれません。なぜなら同じ「メモ帳が hosts を開いている」でも起動のされかたによって渡されている文字列が違うからです。
以下ではコマンドプロンプトで起動した例とタスクスケジューラーで起動した例を比較しています。
コマンドプロンプトでメモ帳を起動します。
cd C:\windows\system32 後に notepad C:\windows\system32\drivers\etc\hosts を実行します。
タスクスケジューラーでメモ帳を起動します。
タスクスケジューラーに以下のような登録をし、登録終了後手動で実行します。
タスクマネージャーで状態を確認します。
コマンドライン列(表示されていないようであればタイトル行を右クリックして列の追加を使って追加してください)を確認すると表示が異なっていることが確認できます。
snmpwalk で確認します。
Bash on Ubuntu on Windows または Hinemos manager などから snmpwalk を実行します。
(snmpwalk の設定方法はここ を参照してください。)
参照する OID は .1.3.6.1.2.1.25.4.2.1.2 (プロセス名) です。notepad.exe が 2 つ表示されることを確認します。
以下の例だと OID 末尾の .8380 や .11172 が PID です。上記タスクマネージャーの表示と合致しているかも確認しておきます。
[root@localhost ~]# snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.25.4.2.1.2 | grep "notepad"
HOST-RESOURCES-MIB::hrSWRunName.8380 = STRING: "notepad.exe"
HOST-RESOURCES-MIB::hrSWRunName.11172 = STRING: "notepad.exe"
コマンドプロンプト実行の場合
コマンドプロンプトで起動したほうの Path 名と引数を確認します。
Path 名の OID は .1.3.6.1.2.1.25.4.2.1.4.PID, 引数の OID は .1.3.6.1.2.1.25.4.2.1.5.PID です。
コマンドプロンプトで起動した場合は Path 名が null になっている (カレントディレクトリから起動したから) ことと、引数の先頭にスペースが挿入されていることを確認します。
[root@localhost ~]# snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.25.4.2.1.4.8380
HOST-RESOURCES-MIB::hrSWRunPath.8380 = ""
[root@localhost ~]# snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.25.4.2.1.5.8380
HOST-RESOURCES-MIB::hrSWRunParameters.8380 = STRING: " C: \\windows\\system32\\drivers\\etc\\hosts"
タスクスケジューラーでの実行の場合
タスクスケジューラーでの実行の場合 Path 名が full path になっていることと、引数の先頭にスペースが挿入されて「いない」ことを確認します。
タスクマネージャーの表示ではスペースがあるように見えますが、snmpwalk で取得した文字列には「スペースはない」点にも注意です。(=タスクマネージャーの表示に全幅の信頼がおけるわけではないということ)
[root@localhost ~]# snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.25.4.2.1.4.11172
HOST-RESOURCES-MIB::hrSWRunPath.11172 = STRING: "c:\\windows\\system32\\"
[root@localhost ~]# snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.25.4.2.1.5.11172
HOST-RESOURCES-MIB::hrSWRunParameters.11172 = STRING: "C: \\windows\\system32\\drivers\\etc\\hosts"
コマンドライン文字列には「ゆれ」がある。
従って、プロセス監視のコマンドラインと引数は上記のような「ゆれ」が発生することを念頭に置いて設定する必要があります。
また、正規表現と言いながら部分一致の正規表現 (例えば "notepad" と指定すること) ではマッチしません。なのでコマンドおよび引数の文字列全体に対してマッチする正規表現を作る必要があります。
このようなことから、想定されるコマンドライン文字列に対して設定する正規表現文字列がマッチするかを事前に検証しておいたほうが賢明です。
たとえば上記の例の場合、Windows 環境であれば Powershell を使用して確認することができます。
" c:\windows\system32\drivers\etc\hosts" -match "^(|.*\\)*hosts *$"
ただ powershell での確認は OK でも Hinemos java の正規表現を使っているのでうまくマッチしない場合があるかもしれません。その場合は java を使って確認する必要がありますが jre ではなく jdk のインストールが必要など敷居が高いです。
java で確認する場合は、例えば以下のように行います。
確認用プログラム (regcheck.java) を作成します。
public class regcheck {
public static void main(String[] args) {
System.out.printf("target : %s\n", args[0]);
System.out.printf("pattern: %s\n", args[1]);
java.util.regex.Pattern p = java.util.regex.Pattern.compile(args[1]);
java.util.regex.Matcher m = p.matcher(args[0]);
System.out.println(m.matches());
}
}
コンパイルします。(javac は jdk のインストールフォルダの bin の中にあります)
C>javac C:\Users\user01\Desktop\regcheck.java
実行します。
C>java -cp C:\Users\user01\Desktop regcheck " c:\\windows\\system32\\drivers\\etc\\hosts" "^(|.*\\)*hosts *$"
target : c:\\windows\\system32\\drivers\\etc\\hosts
pattern: ^(|.*\\)*hosts *$
true
その他注意点
どうも日本語 (ASCII 文字以外) のコマンドおよび引数はうまく認識しない感じがします。
具体的には Windows の SNMP は Shift JIS のバイトストリームを戻しているのに対し Hinemos は UTF-8 でデコードしている感じです。
設定で変わるのかもしれませんが、その設定どこにあるかは分かっていません。
SNMP 監視もプロセス監視も文字コードの設定はなく、SNMP TRAP 監視だけが文字コードの設定を持っているので問答無用で UTF-8 デコードなのかもしれませんが。(それだと困りますが、さりとてソースを読む気はないのです・・・)
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2018年1月13日
この記事 (http://ooltcloud.sakura.ne.jp/blog/201801/article_06231953.html ) の続きです。
以下はこの記事で作成したリポジトリの登録を前提としています。
Windows サービス監視は監視設定そのものよりも以下手順の項目 1 と項目 2 の作業が重要です。
この設定に失敗していると監視設定とにらめっこしても一向に監視できるようにならないので要注意です。
サービス監視対象のノードの WinRM を有効にします。
設定方法の詳細はこちら (http://ooltcloud.sakura.ne.jp/blog/201801/article_06224628.html ) を参照してください。
(wsmancli のインストールは不要です)
サービス監視対象のノードの設定で WinRM のためのユーザーとパスワードを設定します。
“リポジトリ[ノード]” の監視対象ノードをクリックします。
開いたノードの変更ダイアログの中ほどに「サービス→ WinRM」という項目があります。
そこにユーザ名とパスワードを設定する箇所があるので、上記 WinRM をセットアップしたときに用意したユーザー名とパスワードを設定します。
「監視設定パースペクティブ」を開き “監視設定[一覧]” ウインドウの「+」ボタンを押します。
Windows サービス監視を選択します。
設定を行います。
今回はテスト対象のサービスとして Windows Time を使います。なのでサービス名に W32time を設定します。
(表示名である「Windows Time」ではなく、サービス名である「W32time」を指定します。また「w32tm」でもありません。)
また、以下の項目も画面の通りに設定します。
監視項目 ID
スコープ
間隔
監視
通知ID
アプリケーション
設定が追加出来ていたら OK です。
Windows Time は起動しているので、しばらくすると「情報」が記録されるのを確認します。
Windows Time サービスを停止します。
しばらくすると「危険」が記録されるのを確認します。
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2018年1月6日
実際に Hinemos で ping 監視を行ってみます。
今回はメール通知などで外部に通知することはせず、監視履歴パースペクティブに表示するところまでを行います。
監視履歴パースペクティブには、現在の状態を示す “監視履歴[ステータス]” ウインドウと、履歴を示す “監視履歴[イベント]” ウインドウがあります。とりあえず今回はこの画面をみていれば監視ノードの状況が分かることを目指します。
今回の手順は以下のような感じで行います。
新規監視ノードの追加
PING 監視の設定
PING 監視の動作確認
性能表示の確認
新規監視ノードの追加
スタートアップパースペクティブで「リポジトリパースペクティブ」を選択します。
“リポジトリ[ノード]” ウインドウ上で右クリック→「作成」を選択します。
ノードの作成ダイアログが出ます。赤色の箇所が必須入力項目です。
監視対象ノードに SNMP agent がいればデバイスサーチすることである程度自動入力をしてくれます。
監視対象ノードに SNMP agent がいない場合は手入力します。
ファシリティ ID は作成の時のみ変更可能で以後変更不可となるので慎重に決定します。
(自動入力の内容でよいかを再確認します)
ファシリティ名は Hinemos 内での名称です。ホスト名などとは別の名称に設定できます。
「登録」を押し “リポジトリ[ノード]” ウインドウに追加されればノードの追加は終了です。
追加したノードの情報を確認します。
“リポジトリ[ノード]” ウインドウに表示されているノードを選択(ダブルクリック)すると、先ほど入力したときと同じダイアログが表示されます。
設定に変更がある場合はここで入力します。(しかし前述のとおりファシリティ ID は変更できません。)
PING 監視の設定
テストのための前準備として、監視対象ノード (Windows) のファイアウォール設定で ping 応答を戻さない設定にします。
「セキュリティが強化された Windows ファイアウォール」をひらき、「受信の規則」の「ファイルとプリンターの共有 (エコー要求 - ICMPv4 受信)」を無効にします。(しかしなんで「ファイルとプリンターの共有」カテゴリーなんでしょうね・・・?)
スタートアップパースペクティブで「監視設定パースペクティブ」を選択します。
まず “監視設定[通知]” ウインドウを確認します。(*1)
今回はテストの都合で STATUS FOR POLLING と EVENT FOR POLLING の設定を変更します。
(*1)
しかしこの “監視設定[通知]” ウインドウの役割がいまひとつ分かりにくいのですが、要するに監視で何かを見つけた時に「何をするか」が登録されています。
具体的には “監視履歴[ステータス]” ウインドウに表示にしたい場合はステータス通知、“監視履歴[イベント]” ウインドウに表示したい場合はイベント通知を使用します。
デフォルトで登録されている通知 ID で STATUS FOR POLLING と STATUS FOR TRAP がありますが、通知 ID の名称に機能的な意味はありません。なので例えば TRAP でない監視に STATUS FOR TRAP を割り当てることは可能です。なぜなら中身はどらちも「ステータス通知」だからです。通知 ID の名前に惑わされないように注意します。
またコマンド通知は hinemos manager がホストされているマシンでのコマンド実行です。監視ノード側でコマンド実行をしたい場合は JOB 通知の方を使用します。
“監視設定[通知]” ウインドウの「STATUS FOR POLLING」をダブルクリックします。
「有効にした直後は通知しない」にチェックを外します。
「常に通知する」にチェックを入れます。(入っていることを確認します。)
「情報」にチェックを入れます。(全てのステータスにチェックが入っていることを確認します。)
“監視設定[通知]” ウインドウの「EVENT FOR POLLING」をダブルクリックします。
「有効にした直後は通知しない」のチェックを外します。
“監視設定[一覧]” ウインドウで右クリック→「作成」を押します。右クリックでなくても「+」ツールボタンを押しても OK です。
「PING 監視」を選択します。
PING 監視の各パラメーターを設定します。
「監視項目 ID」 は ID なのでファシリティ ID の時と同様に新規登録時のみ設定可能です。後からの変更できないので慎重に決定します。
「アプリケーション」というよくわからない入力項目がありますがこれはこの監視の名前です。任意の文字列を入力します。(*2)
(*2)
アプリケーションというから何か外部プログラムとか API とかを書かないといけないような印象がありますが、この項目にそのような意味はありません。ただの文字列なので何を設定してもよいです。この文字列は監視履歴のウインドウなどに表示されるので、この監視が何の監視であるかが分かる文字列が設定されていればよいです。
また、ファシリティ ID に対してファシリティ名が対応しているように、監視項目 ID に対してアプリケーションが対応しています。であれば監視項目 ID の下にアプリケーションの入力欄があればいいのでは?という疑問が湧きますが、通知で使われる名称なので通知のカテゴリーに移動してしまっているのではないかと思います。(多分。根拠はない)
・・・しかしこの「アプリケーション」という表記、これってインフラ専業のひとには分かりやすい表記なんですかね? 「監視名」ではだめだったのだろうか。Hinemos は「契機」なる IT っぽくない日本語を使っているので、だったらアプリケーションも日本語で書けばいいのにとか思ってしまう。(「契機」のほうはイベントと称すると監視対象のイベントと被るからそう呼んでいるのだろうか?)
スコープを「登録ノードすべて」にします。
スコープという言葉がわかりにくいのですが、要するに「PING 監視を行うノードはどこですか?」ということです。特定のノードならそれを、全部とか特定のグループであればそれを選択すれば対象のノードを監視するようになります。
通知に「STATUS FOR POLLING」と「EVENT FOR POLLING」を設定します。
その他の情報を設定します。
監視 ID を PING_01 にします。
条件の間隔を 1 分にします。
情報 (正常値) の応答時間を 10ms 以下にします。
警告の応答時間を 100ms 以下にします。
アプリケーションを PING監視(全ノード) にします。
収集にチェックを入れます。
OK を押し、"監視設定[一覧]" に登録されれば OK です。
PING 監視の動作確認
スタートアップパースペクティブで「監視履歴パースペクティブ」を選択します。必要に応じて更新ツールボタンを押します。
監視履歴パースペクティブを確認します。
現在、監視対象ノードに PING は通らないので、しばらくすると「危険」が“監視履歴[ステータス]” ウインドウと“監視履歴[イベント]” ウインドウの両方に表示されます。
対象ノードに PING が通るようのファイアウォール設定で ping 応答を戻す設定にします。
「セキュリティが強化された Windows ファイアウォール」をひらき、「受信の規則」の「ファイルとプリンターの共有 (エコー要求 – ICMPv4 受信)」を有効にします。
しばらくすると(1分後) 表示がかわることを確認します。
“監視履歴[ステータス]” ウインドウは「危険」が「情報」に変わることを確認します。
“監視履歴[イベント]” ウインドウは「危険」は消えずに「情報」が追加されることを確認します。
“監視履歴[ステータス]” ウインドウに登録されたエントリーをすべて消去します。
対象を選択して、右クリック→「削除」、または「×」ツールボタンで押下で消すことができます。
“監視履歴[イベント]” ウインドウに登録されたエントリーをすべて消去します。
対象を選択して、右クリック→「確認」、または「☑」ツールボタン押下で消すことができます。
しばらくすると(1分後) 表示がかわることを確認します。
“監視履歴[ステータス]” ウインドウに再び「情報」が表示されることを確認します。
“監視履歴[イベント]” ウインドウの方は変化しないことを確認します。
(この動作は上記で STATUS FOR POLLING で「常に通知する」「情報を通知」を設定し、EVENT FOR POLLING では「通知しない」に設定したからです)
性能表示の確認
パースペクティブ→パースペクティブ表示を選択します。
性能を選択します。
性能パースペクティブが表示されます。
表示されますが、Web ブラウザを小さめに表示していると以下のように表示され「適用」ボタンが見えないことがあります。
適用ボタンの表示します。
SXGA (1280*1024) のディスプレイで Web ブラウザを最大化表示すると、やっと「適用」ボタンが現れます(汗
Web ブラウザを最大化しても表示されない場合
ディスプレイが 1366 * 768 や 1280 * 800 の画面で最大化しても「適用」ボタンが表示できない場合、「適用」ボタンを押したいときだけ、ブラウザの拡大縮小表示を使用して縮小させます。(*3)
(*3)
サーバーのコンソールの主流が SXGA かもしれないけど、縦の解像度が足らないとボタンが表示されないってデザインはどうなんですかね?という気がとてもします。
性能グラフの表示
性能が参照したいノードを選択して「適用」ボタンを押すとグラフが表示されます。
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2018年1月6日
なにやら WinRM という仕組みがあるようです。
そもそも WinRM って何かというと、ザクっといえば WMI (Windows Management Instrumentation) を Webサービス (WS-Management プロトコル, HTTP SOAP ベース, WS は WebService の略) でアクセスできる版、みたいなやつらしいです。一方 WMI は DCOM ベースのアクセスらしいです。しかし WMI 自体が WBEM (Web Based Enterprise Management) の Microsoft の実装なので Web なんじゃないの?という話なわけですが、まあそれを言ったら DCOM も ActiveX だったりするわけで Web ですよね、みたいな話なのかな? このあたりの関係性はよくわかりませんが・・・
なにはともあれ有効にしてみます。
管理者権限でコマンドプロンプトを起動します。
winrm qc を実行します。
qc は QuickConfig の略らしいです。
winrm qc
WinRM サービスを開始します。
WinRM サービスを開始します。変更しますか [y/n]? と聞いてくるので y を押します。
しかしここで public なネットワークに接続していると失敗します。
WinRM はこのコンピューター上で要求を受信するように設定されていません。
次の変更を行う必要があります:
WinRM サービスを開始します。
変更しますか [y/n]? y
WinRM は要求を受信するように更新されました。
WinRM サービスが開始されました。
WSManFault
Message
ProviderFault
WSManFault
Message = このコンピューターのネットワーク接続の種類の 1 つが Public に設定されているため、WinRM ファイアウォール例外は機能しません。 ネットワーク接続の種類を Domain または Private に変更して、やり直してください。
エラー番号: -2144108183 0x80338169
このコンピューターのネットワーク接続の種類の 1 つが Public に設定されているため 、WinRM ファイアウォール例外は機能しません。 ネットワーク接続の種類を Domain ま たは Private に変更して、やり直してください。
なので WinRM を有効にする PC はルーターの内側にあるか、または public なネットワークにつながっていない状況で実行します。
ところが Hyper-V をインストールしていたりしますと仮想 NIC が作成されていますが、それが「識別できないネットワーク」になっていると public 扱いされてはねられてしまいます。そういう場合はグループポリシーを操作するなどをして、一時的にでも public ネットワークが存在しないようにします。
あらためて WinRM の設定を行います。
WinRM サービスを開始します。変更しますか [y/n]? で y を
WinRM ファイアウォールの例外を有効にします。~ 変更しますか [y/n]? で y を選択します。
C>winrm qc
WinRM はこのコンピューター上で要求を受信するように設定されていません。
次の変更を行う必要があります:
WinRM サービスを開始します。
変更しますか [y/n]? y
WinRM は要求を受信するように更新されました。
WinRM サービスが開始されました。
WinRM は、管理用にこのコンピューターへのリモート アクセスを許可するように設定されていません。
次の変更を行う必要があります:
WinRM ファイアウォールの例外を有効にします。
ローカル ユーザーにリモートで管理権限を付与するよう LocalAccountTokenFilterPolicy を構成してください。
変更しますか [y/n]? y
WinRM はリモート管理用に更新されました。
WinRM ファイアウォールの例外を有効にしました。
ローカル ユーザーにリモートで管理権限を付与するよう LocalAccountTokenFilterPolicy を構成しました。
LocalAccountTokenFilterPolicy ってのは リモート UAC のことらしいです。(=リモート接続で権限が昇格するようにする)
WinRM を使用してデータを取ってみます。
サービスの一覧を取得します。 e というのは enumerate の略です。wmicimv2/Win32_Service というのはアクセスするリソース名のようです。wmicimv2/~ で wmi のクラス名を指定すれば取得できるようです。
winrm e wmicimv2/Win32_Service
特定のサービスの情報を取得する場合は get を使用します。取得するサービス名は指定は「?Name=サービス名」といった形式で指定します。
winrm get wmicimv2/Win32_Service?Name=W32time
Linux からのアクセスが可能なように構成します。
現在の設定を確認します。デフォルトの設定では Basic 認証が無効 (Basic = false), 平文が不可 (AllowUnencrypted=false) になっているはずです。
winrm get winrm/config/service
Linux からのアクセスを可能にするため Basic 認証を有効、平文を許可にします。
(もっとセキュアな設定はあると思いますが、ここでは考えないことにします)
winrm set winrm/config/service/auth @{Basic="true"}
winrm set winrm/config/service @{AllowUnencrypted="true"}
CentOS からアクセスできるかを確認します。
まず wsmancli のインストールをします。
yum install wsmancli
CentOS ではなく Ubuntu や WSL (Bash on Ubuntu on Windows) など Debian系Linux の場合は apt-get します。
apt-get install wsmancli
以下のような感じでアクセスします。
この際、user はドメインユーザーは指定できません。なので WinRM でアクセスする用のローカルユーザーを作成して置く必要があります。
wsman -u [localuser] -p [password] -y basic -h 127.0.0.1 -P 5985 enumerate http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service
wsman -u [localuser] -p [password] -y basic -h 127.0.0.1 -P 5985 get http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service?Name=W32time
posted in Linux , OS , Windows , WMI , サーバー管理 , 環境設定 by ooltcloud | No Comments
2017年12月26日
Hinemos 6 agent for windows のインストールの手順のメモ。詳細は https://github.com/hinemos/hinemos/blob/master/README.jp.md にある「インストールマニュアル ( doc_install_linux_6.0_ja.pdf )」を参照してください。ファイル名に linux が入っていますが 7 章に Windows 版 agent のインストールについて書かれています。
以下は上記文書の手順を元にアレンジしています。なのでうまく行く保証はないです。正確を求める場合は上記文書を参考にしてください。
ファイアウォールの設定
hinemos Agent は UDP 24005 を待ち受けるようなので穴を開けます。
加えて、SNMP の穴も開けます。
Windows に SNMP を導入
以下は Windows 10 の例です。「コントロールパネル」→「プログラムのアンインストール」を選択し、「Windows の機能の有効化または無効化」→「簡易ネットワーク管理プロトコル(SMMP)」を選択します。
Windows Server の場合はサーバーマネージャーで「管理」→「役割と機能の追加」を選択し、機能の追加で同じもの(=SNMP サービス)があるのでそれを選択します。
Java のインストール
Hinemos 6 の agent は java 8 で実装されているので jre をダウンロードおよびインストールします。
インストール後、インストールされたフォルダを確認しておきます。
環境変数 JAVA_HOME の設定
システム環境変数に JAVA_HOME の設定を追加します。
Hinemos agent のインストール
Hinemos のダウンロードサイト (https://github.com/hinemos/hinemos/releases/tag/v6.0.0 ) から Hinemos agent (今回は hinemos-agent-6.0.0-1.win.zip) をダウンロードし、その中に含まれている msi を実行します。
ただし UAC が有効の場合、普通に msi を実行すると以下のようなエラーが発生してインストールできません。
インストール手順 (https://github.com/hinemos/hinemos/releases/download/v6.0.0/doc_install_6.0_ja.pdf ) によれぱ、意訳すると、UAC を無効にするか、Administrator ビルトインアカウントでの実行が必要があるとのこと。
ですが、それはいささか面倒なのでコマンドプロンプトを管理者権限で起動し、そこから msi を実行することでインストールします。
以下のように「Click the Finsh Button ~」と出れば OK です。しかしこれは正規の手順ではないので気になる人は公式の手順書通りにインストールしましょう。
hinemos agent をサービスとして登録
環境変数 JAVA_HOME の位置に JAVA がインストールされていることを再度確認します。たとえば JAVA_HOME に設定されているフォルダが存在していることを確認するのは以下のようにします。
IF EXIST "%JAVA_HOME%" ECHO OK
"OK" が表示されたら、C:\Program Files (x86)\Hinemos\Agent6.0.0\bin にある RegistAgentService.bat を実行します。
"successfully installed" と表示されれば OK です。
SNMP サービスの再起動とコミュニティの設定
SNMP サービスを一旦停止しコミュニティ名を確認します。コミュニティ名の変更が必要であれば変更します。コミュニティ名の確認が終了したら SNMP サービスを再起動します。
可能なら snmpwalk で hinemos agent の拡張 MIB にアクセスできるかどうかを確認します。
たとえば以下のように、.1.3.6.1.4.1.2021 にアクセスし値がもどってくれば OK です。
[root@localhost ~]# snmpwalk -v 2c -c Public xxx.xxx.xxx.xxx .1.3.6.1.4.1.2021
UCD-SNMP-MIB::memTotalSwap.0 = INTEGER: xxxxxxxx kB
Himemos Agent の起動
Hinemos Agent の Service を起動します。起動できれば終了です。
ここでエラーが発生する場合 JAVA_HOME の内容を確認し、JAVA_HOME が指す位置に java がインストールされていることを再確認します。
p.s.
しかし UAC の無効が推奨というのはどうなのだろう?今回のテストのような Client OS への agent のインストールは本来想定していないという話であれば、Server OS は Administrator アカウントが無効になっていないのでそれを使えばいいと言われればそうなのですが。
また hinemos manager のインストールでも SELinux は無効というのがありました。アプリケーションの都合でセキュリティ要件を下げるというのはよくある話ではありますが、監視システムがセキュリティ要件を下げるってのはどうなんだろう?
・・・などと言う点が気になりました。このあたりは世のシステム管理者さんはあまり気にはしないのだろうか?
posted in Hinemos , OS , Windows , サーバー管理 by ooltcloud | No Comments
2017年12月24日
この記事はそんな広島 の 12/7 の記事(ということで 12/24 に書いたもの)です。
広島にはその筋(?)には有名な中山踏切という、温品方面からの車と戸坂方面からの車が合流する交通の要衝(?)であり渋滞ポイントでありながら、信号機が設置されておらず、踏切があるがゆえに右折はもちろんのこと左折直進もままならぬ(踏切手前の一時停止 / 線路内一時停止不可の縛りがある)という結構嫌われている交差点があります。
場所はここ。(上の写真とは南北逆です)
信号機がないのにどうやって通過するかというと阿吽の呼吸を使います。つまり互いに牽制しつつ割り込んでいく形ですね(汗
遮断機が下りている間は戸坂方面からの車は右折のチャンスなので対向車線を逆走をするというカオスな状況も時折起こります(汗
なのでタイミングが分からない経験値が少ない人や、そもそもそういう牽制とかが苦手な人はこの交差点は通りたくないと口を揃えます(汗
で、この交差点。現在広島高速 5 号線建設に伴って工事中のようでして、信号がつくかどうかはしりませんが交差点の領域は広くなるようです。多分右折レーンができる。(根拠のない予想)
かつて中山踏切 - 第一病院間は、現在の中山踏切 - 矢賀駅間と同じ程度に隘路でした。時代を経て道幅が広くなり通行しやすくなるのはよいことなのですが、往時の姿を無くすという側面もあり、諸行無常、一抹の寂しさをおぼえるのも事実でありまして、なのでここに記録として現在の姿をちょっと残しておくことに。
以下は中山踏切バス停方向から温品方向を望んだところ。
温品方向から中山踏切バス停方向を望んだところ。左手前方に広島高速 5 号線の工事中の高架の橋桁が見える。(わかりにくいけど)
以下は Theta で撮影した 360° 画像。掴んで回せます。ここのライブラリを使わせてもらいました。(https://github.com/aike/thview.js )
踏切の手前から。
踏切と横断歩道を渡り、交差点の中央あたりから。
バス停側横断歩道の前から。
Theta で撮影した写真を blog に上げたかっただけなのでは?という疑惑がありますが、それは誤解ということにしておいてください(ぇ
posted in 与太話 by ooltcloud | No Comments
2017年12月22日
Excel 2010 で動いていたマクロが Excel 2013 や 2016 で動かすと挙動が異なって困った経験はありますか?私はあります(汗
結論からいうと、私が経験した事例では以下のようなことに気を付ける必要があります。
使用しないセルに条件付き書式を残さないようにする。
条件付き書式でユーザー関数を呼ぶ場合、そのユーザー関数内でエラーが生じないようにする。
よくわからない。「ともあれこれをしておけばいい」的な対処方法はないの?という場合は、マクロの開始直後と終了直前に EnableFormatConditionsCalculation を操作を追加します。以下は ActiveSheet に対して操作を追加した例です。
Sub Macro1()
' 条件付き書式の適用を停止
ActiveSheet.EnableFormatConditionsCalculation = False
' Excel 2010 まで動いていたマクロの処理
' 条件付き書式の適用を再開
ActiveSheet.EnableFormatConditionsCalculation = True
End Sub
再現手順を以下に示します。(以下の手順は Excel 2013 64bit 版 を Windows 10 (Ver1703) 64bit 版で確認しています)
何が起こるかを一言でいうと、マクロのプログラムカウンターが途中で消失します。つまりマクロが最後まで実行されません。(= End Sub まで行かない)
Module1 シートに FuncA ユーザー関数を作成します。また作成するユーザー関数は a = 0 のときにエラーが発生するようにします。(配列でない変数を配列としてアクセスしようとしています)
Function FuncA(a As Integer) As String
Dim b As Variant
If a = 0 Then
c = b(1)
End If
End Function
A1 セルに FuncA() を使用した条件付き書式を設定します。今回は FuncA(自身のセル) が "" のときセルの色を替えるようにします。A1 セルの値を 1 とします。
A1 セルを A2 にコピーします。A2 セルの値(数式)は =A1+1 に変更します。
B1 セルに A1 セルをコピーします。B1 セルの値はクリアします。従ってセルの色が変更されないことを確認します。また合計 3 つのセルに同じ条件付き書式が設定されていることを確認します。
Module2 シートに Macro1() を作成します。内容はなにも設定していないセルをクリアするだけのものです。今回は C1 セルと C2 セルをクリアするマクロを作成します。
Sub Macro1()
Range("C1").ClearContents
Range("C2").ClearContents
End Sub
動作の確認のために作成したマクロの全ての行にブレイクポイントを設定します。また End Sub の部分にもブレイクポイントを設定します。
Sub Macro1() から End Sub までの間にカーソルを置いた後に F5 キーを押しマクロを実行します。ブレイクポイントで停止しされるのを確認しながら、繰り返し F5 キーを押し End Sub までプログラムカウンタ (黄色の表示) が移動していくのを確認します。 (=期待通りに動作する)
End Sub の実行も終了したら C1 セルのクリアを D1 セルのクリアに変更します。またこの操作はマクロのプログラムコードを変更することのみが目的です。D1 セルに変更すること自体に意味はありません、C1 以外ならどこのセルでも OK です。
F5 を押しマクロを実行します。D1 セルのクリアのところでブレイクする(黄色表示になる)ことを確認します。
ふたたび F5 を押しマクロを実行します。D1 セルのクリアの行を実行の後 C2 セルをクリアする行にプログラムカウンタが移動してブレイクされる(C2 セルのクリアのところが黄色表示になる)のを期待しますが、プログラムカウンタ (黄色の表示) は消失したまま戻ってきません。また、A2 のセル色が白になってしまいます。
また B1 セルに空白や 0 以外の値を入れ上記手順を行った場合は本現象は再現しません。以下は B1 セルに値を入れてから、マクロの変更した D1 セルのクリアを C1 セルのクリアに戻して F5 を押していった場合です。プログラムカウンタ (黄色の表示) は End Sub まで移動します。(=期待通りに動作する)
この現象は条件付き書式で呼んだユーザー関数がエラーを起こした場合に発生します。エラーがない場合は発生しません。
しかも意図しない動作となるのは問題のある条件付き書式側の処理ではなくて、エラーが発生する関数とはまったく関係のないマクロ側だということです。マクロが途中で止まるからと言ってマクロ側のコードを一生懸命眺めても、マクロ側にはエラーはないので解決の糸口がつかめないのが特徴です(汗
そしてこの現象は Excel のバグか?(ディグレードか?)というと、そうであろうと思います。(厳密には「バグ」ではなく「未定義の動作」なのだろうけども。)
しかしこの現象を発生させるためにはユーザー関数のコードがバグっている必要があるのです。なので、自分の作りこんだバグを棚に上げて Microsoft を非難するわけにも・・・とモニョってしまうわけですね(汗
ともかくも大切なことは、この現象は不要となった条件付き書式を設定したセルが放置されることによって起きる可能性が高いことです。少なくとも私が遭遇した事例はそうでした。今回の B1 セルのように見た目は異常がない場合はそれが原因になっているとは想像することすら難しいです。
従って不要な条件付き書式付きセルが残らないようにする必要があります。残っているとパフォーマンスも無駄にしますのできれいさっぱり削除しましょう。
いやそうはいってもチェックするのは大変すぎて・・・という場合は冒頭の通り EnableFormatConditionsCalculation で対応してみてください。おそらく期待通りに動作するはずです。しかし EnableFormatConditionsCalculation = True より後のコードを実行しない場合があるので EnableFormatConditionsCalculation = True より後には処理は入れないようにします。
Sub Macro1()
' 条件付き書式の適用を停止
ActiveSheet.EnableFormatConditionsCalculation = False
' Excel 2010 まで動いていたマクロの処理
Range("D1").ClearContents
Range("C2").ClearContents
Range("D3").ClearContents
' 条件付き書式の適用を再開
ActiveSheet.EnableFormatConditionsCalculation = True
' ここより下は実行されない場合がある
End Sub
本質的な解決は条件付き書式の条件でエラーを発生されないこと、ユーザー関数でエラーを出さないことなので、その点は踏まえたうえで EnableFormatConditionsCalculation は次善の対策とするようにしてください。
posted in Excel , Office by ooltcloud | No Comments
2017年12月21日
tags: SNMP posted in OS , SNMP , Windows , サーバー管理 by ooltcloud | No Comments
2017年12月19日
ミドルウェアソフトウェアが Windows の SNMP サービスを使用して拡張 MIB を用意するケースがありますが、どのミドルウェアが用意しているのかを調査する方法のメモ。
HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ExtensionAgents に拡張 MIB が登録されています。拡張 MIB が一切ない場合は ExtensionAgents のキー自体がありません。ExtensionAgents に登録されている値の名前や値自体をみれば、どのミドルウェアが用意したのか大体わかります。
以下は hinemos が拡張している例です。
PS>gi HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ExtensionAgents
Hive: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SNMP\Parameters
Name Property
---- --------
ExtensionAgents hinemos_agent : SOFTWARE\HinemosAgent\SNMPExtAgent
ExtensionAgents の値は HKLM (\HKEY_LOCAL_MACHINE) なので、それを繋いでやればその先に何が登録されているのかが分かります。ただ、SOFTWARE の次に WOW6432Node を挟まないと参照出来ない場合もあるので注意です。
PS>gi HKLM:\SOFTWARE\WOW6432Node\HinemosAgent\SNMPExtAgent
Hive: HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\HinemosAgent
Name Property
---- --------
SNMPExtAgent Pathname : C:\Program Files (x86)\Hinemos\Agent6.0.0\lib\HinemosSNMPExtAgent.dll
tags: SNMP posted in OS , SNMP , Windows , サーバー管理 by ooltcloud | No Comments
2017年12月17日
NET-SNMP をインストールすれば Windows でも MIB を参照できるのですが、しかしそういうツールを持ち込めない環境というのもあってそういう場合に困ります。そういう状況で MIB を参照したい場合は Oleprn というライブラリを使うことで SNMP が喋れるようです。(名前からするとプリンターのステータスを拾うためのライブラリなんですかね?)
名前からして OLE なので Excel がインストールされているなら Excel VBA で扱うのがインテリセンスも効くので楽です。
VBE (ALT+F11) をひらき、標準モジュールを作成して参照設定から oleprn 1.0 Type Libraty にチェックを入れます。
コードを入力して実行します。
上記で入力したコードは以下
Sub test()
Dim snmp As New OLEPRNLib.snmp
' VBScript : snmp = CreateObject("OlePrn.OleSNMP")
' Powershell : $snmp = New-object -ComObject olePrn.OleSNMP
snmp.Open "192.168.0.1", "public"
getValue = snmp.Get(".1.3.6.1.2.1.1.5.0")
Debug.Print getValue
snmp.Close
End Sub
いや「Excel もないんです」という場合は vbscript を使うとかします。たぶん上記のコードの Dim snmp As New OLEPRNLib.snmp の部分を snmp = CreateObject("OlePrn.OleSNMP") にすれば動くのではないかと思います。
set snmp = CreateObject("OlePrn.OleSNMP")
snmp.Open "192.168.0.1", "public"
getValue = snmp.Get(".1.3.6.1.2.1.1.5.0")
WScript.Echo getValue
snmp.Close
Powershell でやりたい場合も同様です。変数名とか関数の括弧とかに注意する程度です。
$snmp = New-object -ComObject olePrn.OleSNMP
$snmp.Open("192.168.0.1", "public")
$snmp.Get(".1.3.6.1.2.1.1.5.0")
$snmp.Close()
ただ、OID 番号で指定しないとならないのと snmpwalk のような列挙ができないので使えるシーンは限られるとは思います(汗
tags: SNMP posted in OS , SNMP , Windows , サーバー管理 by ooltcloud | No Comments
2017年12月17日
個人的には使うことはないと思うのですが、ちょっと試してみたのでメモ。
インストール
インストールオプションは一切なしでも snmpwalk と snmptranslate は動作します。
しかしデフォルトのインストールディレクトリは C:\usr ですが、それでも Path が長すぎるというエラーを吐きます。
snmp.conf の位置と MIB ファイルの追加
C:\usr\etc\snmp に snmp.conf があるのでそこに追記します。
mibdirs のディレクトリの区切りは ; (セミコロン) を使用するようです。Linux 系の : (コロン) とは異なることに注意します。
mibdirs C:/usr/share/snmp/mibs; C:/usr/share/snmp/mibs/screenos/6.2.0.mibs/snmpv2
mibs all
persistentDir C:/usr/snmp/persist
tempFilePattern C:/usr/temp/snmpdXXXXXX
コマンド類の Path は C:\usr\bin です。
インストール時に PATH は追加してくれないので、snmpwalk や snmptranslate を使用する場合は c:\usr\bin に移動してから使うか、自分で環境変数 PATH に c:\usr\bin を追加します。
使用上の注意
仕様なのかバグなのか分かりませんが、OID に . (ドット) のみを指定するとエラーになります。.1 と指定します。
また -Of などのオプションを OID の後に入れてもエラーになります。オプション類は先に記述するようにしましょう。
snmpwalk -c public -v 2c 192.168.0.1 .1
おまけ: SNMPd の起動
インストールのとき Net-SNMP Agent Service の Standard Agent か With Windows Extension DLL Support のいずれかを選ぶと(両方は選べない) C:\usr\bin\ の snmpd.exe が使えるようになります。
Standard Agent か With Windows Extension DLL Support の違いは、Windows が標準で持つ C:\Windows\System32\inetmib1.dll や C:\Windows\System32\snmpmib.dll を使用するかどうかの差であるようです。後者は使用し前者は使用しないようです。
後者の場合に Windows の機能の SNMP サービスがインストールされていると snmpd.exe の起動時にエラーが発生するのでインストール自体をしないようにします。前者の場合でも SNMP サービスが動作していると Listen ポートが競合し snmpd.exe が abort するので SNMP サービスは停止しておく必要があります。
また、snmpd.exe の実行の前に C:\usr\etc\ に snmpd.conf を設定しておく必要があります。例えば以下のような定義をします。(設定の詳細は他のサイトを探してください)
com2sec public default public
group public v2c public
view all included .1 ff
access public "" any noauth exact all none none
tags: SNMP posted in OS , SNMP , Windows , サーバー管理 by ooltcloud | No Comments
2017年12月17日
NET-SNMP の使い方のメモ。
(といっても、MIB の参照するために必要な 2 つのコマンドの主要なオプションのみメモ)
snmpwalk
実際にエージェントの MIB を参照しその値を表示します。
以下は .1.3.6.1.2.1.1.5 を参照した例
# オブジェクトを参照する
# snmpwalk -c コミュニティ名 -v SNMPバージョン 機器のアドレス OID
[root@localhost ~]# snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.1.5
RFC1213-MIB::sysName.0 = STRING: "Router1"
# -Of をつけて OID シンボルで表示
[root@localhost ~]# snmpwalk -Of -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.1.5
.iso.org.dod.internet.mgmt.mib-2.system.sysName.0 = STRING: "Router1"
# -On をつけて OID 番号で表示
[root@localhost ~]# snmpwalk -On -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.1.5
.1.3.6.1.2.1.1.5.0 = STRING: "Router1"
# OIDシンボルで指定
[root@localhost ~]# snmpwalk -c public -v 2c .iso.org.dod.internet.mgmt.mib-2.system.sysName.0
RFC1213-MIB::sysName.0 = STRING: "Router1"
# MIB ファイル名+シンボルで指定 (正確にはファイル名ではなく、MIB ファイルの先頭行で宣言された名前)
[root@localhost ~]# snmpwalk -c public -v 2c RFC1213-IB::sysName.0
RFC1213-MIB::sysName.0 = STRING: "Router1"
列挙する場合は以下のように。
# mib-2.system 以下を列挙
snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.2.1.1
# mib-2 (.1.3.6.1.2.1) 以下を列挙する場合はアドレス指定はなくて良い。
snmpwalk -c public -v 2c 192.168.0.1
# 全部を列挙する場合は . のみを指定
snmpwalk -c public -v 2c 192.168.0.1 .
snmptranslate
MIB ファイルを参照し名前解決を確認します。
snmptranslate は MIB ファイルを参照した結果を表示しているだけなので、snmptranslate で表示で来たからと言って実際の機器にそのオブジェクトがあるとは限らない点、またはアクセス権があるとは限らない点に注意です。(= snmptranslate では成功するが snmpwalk では値が取得できないことがあります)
# MIB ファイル名+シンボルを得る
[root@localhost ~]# snmptranslate .1.3.6.1.2.1.1.5
RFC1213-MIB::sysName
# -Of オプションで OID シンボルを得る
[root@localhost ~]# snmptranslate -Of .1.3.6.1.2.1.1.5
.iso.org.dod.internet.mgmt.mib-2.system.sysName
# -On オプションで OID 番号を得る
[root@localhost ~]# snmptranslate -On .iso.org.dod.internet.mgmt.mib-2.system.sysName
.1.3.6.1.2.1.1.5
# -Tp オプションで MIB ツリーを表示する
[root@localhost ~]# snmptranslate -Tp .1.3.6.1.2.1.1
+--system(1)
|
+-- -R-- String sysDescr(1)
| Textual Convention: DisplayString
| Size: 0..255
+-- -R-- ObjID sysObjectID(2)
+-- -R-- TimeTicks sysUpTime(3)
| |
| +--sysUpTimeInstance(0)
|
+-- -RW- String sysContact(4)
| Textual Convention: DisplayString
| Size: 0..255
+-- -RW- String sysName(5)
| Textual Convention: DisplayString
| Size: 0..255
+-- -RW- String sysLocation(6)
| Textual Convention: DisplayString
| Size: 0..255
+-- -R-- INTEGER sysServices(7)
| Range: 0..127
+-- -R-- TimeTicks sysORLastChange(8)
| Textual Convention: TimeStamp
|
+--sysORTable(9)
|
+--sysOREntry(1)
| Index: sysORIndex
|
+-- ---- INTEGER sysORIndex(1)
| Range: 1..2147483647
+-- -R-- ObjID sysORID(2)
+-- -R-- String sysORDescr(3)
| Textual Convention: DisplayString
| Size: 0..255
+-- -R-- TimeTicks sysORUpTime(4)
Textual Convention: TimeStamp
tags: SNMP posted in SNMP , サーバー管理 by ooltcloud | No Comments
2017年12月17日
標準でインストールされる MIB ファイルだけでは足らない場合 MIB ファイルを追加する必要があります。
以下は ScreenOS 6.2 の MIB ファイルを追加する場合の例です。(CentOS 7, snmpwalk ver5.7.2 の例です)
default の MIB の参照ディレクトリを確認する
snmpwalk を引数なしで実行すると usage が表示されますが、その -M オプションの説明の下に default の MIB ファイルの参照ディレクトリが表示されます。
USAGE: snmpwalk [OPTIONS] AGENT [OID]
(中略)
General options
-m MIB[:...] load given list of MIBs (ALL loads everything)
-M DIR[:...] look in given list of directories for MIBs
(default: /usr/share/snmp/mibs/ )
(以下略)
snmp.conf の場所を確認する
snmpconf を実行すると、現在存在している conf が表示されます。
[root@localhost ~]# snmpconf
The following installed configuration files were found:
1: /etc/snmp/snmpd.conf
2: /etc/snmp/snmptrapd.conf
3: /root/.snmp/snmp.conf
Would you like me to read them in? Their content will be merged with the
output files created by this session.
Valid answer examples: "all", "none","3","1,2,5"
Read in which (default = all):
既に作成されていればそのファイルを編集するか、削除して新しく作るのかを検討します。
また今回は snmpconf で snmp.conf は作りませんが、snmpconf で作成すると最後に以下のようなメッセージがでます。
The following files were created:
snmp.conf
These files should be moved to /usr/share/snmp if you
want them used by everyone on the system. In the future, if you add
the -i option to the command line I'll copy them there automatically for you.
Or, if you want them for your personal use only, copy them to
/root/.snmp . In the future, if you add the -p option to the
command line I'll copy them there automatically for you.
snmp.conf はみんなで使うなら /usr/share/snmp、ひとりで使うなら ~/.snmp に置きましょう、ということですね。
MIB ファイルの配置
ScreenOS 6.2 の MIB を配置します。
今回は /tmp/6.2.0.mibs.zip の内容を /usr/share/snmp/mibs/screenos/ に展開します。
wget https://www.juniper.net/techpubs/software/screenos/screenos6.2.0/6.2.0.mibs.zip -P /tmp
unzip /tmp/6.2.0.mibs.zip -d /usr/share/snmp/mibs/screenos/
snmp.conf の作成
今回は空のファイルから直接テキストエディタを使って snmp.conf を作成します。
mibdirs として上記の default の MIB の参照ディレクトリ(以下の緑マーキング部分)と今回新たに参照するディレクトリ(以下の赤のマーキング部分)を記述します。ディレクトリの区切り文字は : (コロン) です。
次の行に mibs all を追記します。これは mibdirs で見つかったファイル全てを MIB ファイルとして評価するという意味 (らしい) です。
mibdirs /usr/share/snmp/mibs :/usr/share/snmp/mibs/screenos/6.2.0.mibs/snmpv2
mibs all
MIB ファイルが参照されることを確認
snmptranslate で配置した MIB ファイルが参照されることを確認します。
追加配置した MIB ファイルの OID 番号を指定し -Of オプションを指定することで OID シンボルが表示されることを確認します。
[root@localhost ~]# snmptranslate .1.3.6.1.4.1.3224.7.11.1 -Of
(略)
Unlinked OID in NETSCREEN-SET-ADMIN-USR-MIB: nsSetAdminUser ::= { netscreenSetting 11 }
Undefined identifier: netscreenSetting near line 67 of /usr/share/snmp/mibs/NS/NS-SET-ADMIN-USR.mib
.iso.org.dod.internet.private.enterprises.netscreen.netscreenSetting.nsSetAdminUser.nsSetAdminUserLocalTable
上記ではなにかしらのエラーが出ていますが、変換自体はできているので OK です。(多分他の機器の MIB であればエラーは出ないんじゃないかな・・・?)
MIB ファイルの修正
不幸にして ScreenOS 6.2 の MIB ファイルはエラーが発生してしまったので、これを修正してみることにします。
エラーメッセージ(前述の Unlinked OID ~)を読むと「9,49 行目は netscreenSettingMibModule だが、 67 行目は netscreenSetting であり MibModule がない」ということのようです。
なので、9,49 行目の末尾の MibModule を削除し netscreenSetting に統一してみることにします。
・・・というのをエラーがでるすべての mib ファイルで実施します(汗
9: netscreenSettingMibModule
49: ::= { netscreenSettingMibModule 11 }
67: nsSetAdminUser OBJECT IDENTIFIER ::= { netscreenSetting 11 }
そんなのめんどくさい・・・と思う人はこちらで。
cd /usr/share/snmp/mibs/screenos/6.2.0.mibs/snmpv2
sed -e "s/MibModule//" NS-SET-*.mib -i
sed -e "s/MibModule//" NS-VPN-*.mib -i
MIB ファイルを修正後、再度 snmptranslate や snmpwalk を実行し、エラーが出なくなっていれば成功です。
[root@localhost ~]# snmpwalk -c public -v 2c 192.168.0.1 .1.3.6.1.4.1.3224.7.11.1 -Of
.iso.org.dod.internet.private.enterprises.netscreen.netscreenSetting.nsSetAdminUser.nsSetAdminUserLocalTable.nsSetAdminUserLocalEntry.nsAdminUserLocalIndex.0 = INTEGER: 0
.iso.org.dod.internet.private.enterprises.netscreen.netscreenSetting.nsSetAdminUser.nsSetAdminUserLocalTable.nsSetAdminUserLocalEntry.nsAdminUserLocalName.0 = STRING: ns
.iso.org.dod.internet.private.enterprises.netscreen.netscreenSetting.nsSetAdminUser.nsSetAdminUserLocalTable.nsSetAdminUserLocalEntry.nsAdminUserLocalPriv.0 = INTEGER: 250
.iso.org.dod.internet.private.enterprises.netscreen.netscreenSetting.nsSetAdminUser.nsSetAdminUserLocalTable.nsSetAdminUserLocalEntry.nsAdminUserLocalRole.0 = INTEGER: not-assigned(0)
tags: SNMP posted in SNMP , サーバー管理 by ooltcloud | No Comments
2017年12月17日
ともかく SNMP を理解するにはやはり触ってみたい・・・のですが特に Windows の場合、標準状態で SNMP に触る方法がほぼありません(汗
そこで Windows 10 には WSL (Bash on Ubuntu on Windows) があるので、そこに NET-SNMP をインストールして周辺機器 (ルーターとか) の MIB を参照するための環境を構築してみます。また目的は MIB を参照するためだけなので自分自身を SNMP agent にはしないことにします。
ということで、NET-SNMP (Linux版) のインストール手順を以下にメモ。また以下のインストール作業はすべて root で行っています。
Windows 10 (WSL; Bash on Ubuntu on Windows) / Debian 系 Linux の場合。
Windows 10 の場合 x64 であれば WSL (Bash on Ubuntu on Windows) が使えるのでこれを有効にし、NET-SNMP をインストールします。実体は Ubuntu なので、インストールは Debian 系 Linux の作法で行います。
apt-get install snmp
apt-get install snmp-mibs-downloader
download-mibs
apt-get install snmp だけでは mib ファイルが全くインストールされないので apt-get install snmp-mibs-downloader を行いその後 download-mibs を実行します。(参考: https://l3net.wordpress.com/2013/05/12/installing-net-snmp-mibs-on-ubuntu-and-debian/ )
download-mibs が終了したら、snmptranslate を実行して期待する結果が得られるかを確認します。
[root@localhost ~]# snmptranslate .1.3.6.1.2.1.4.20.1.1 -Of
.iso.org.dod.internet.mgmt.mib-2.ip.ipAddrTable.ipAddrEntry.ipAdEntAddr
snmptranslate を実行時に、以下のようなエラーがでる場合があります。
Unlinked OID in IPATM-IPMC-MIB: marsMIB ::= { mib-2 57 }
Undefined identifier: mib-2 near line 18 of /usr/share/mibs/ietf/IPATM-IPMC-MIB
Expected "::=" (RFC5644): At line 493 in /usr/share/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB
Expected "{" (EOF): At line 651 in /usr/share/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB
Bad object identifier: At line 651 in /usr/share/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB
Bad parse of OBJECT-IDENTITY: At line 651 in /usr/share/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB
Bad operator (INTEGER): At line 73 in /usr/share/mibs/ietf/SNMPv2-PDU
この場合、以下を追加で実行します。(参考: https://mistymagich.wordpress.com/2016/07/19/Ubuntu 14.04, Ubuntu 16.04上のsnmpwalk,snmptranslateでエラーが出力される )
wget http://www.iana.org/assignments/ianaippmmetricsregistry-mib/ianaippmmetricsregistry-mib -O /usr/share/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB
wget http://pastebin.com/raw.php?i=p3QyuXzZ -O /usr/share/mibs/ietf/SNMPv2-PDU
wget http://pastebin.com/raw.php?i=gG7j8nyk -O /usr/share/mibs/ietf/IPATM-IPMC-MIB
CentOS / Redhut 系 Linux の場合
CentOS の場合は以下のようにインストールします。
yum install net-snmp
yum install net-snmp-utils
インストール後、snmptranslate を実行して期待する結果が得られるかを確認します。
[root@localhost ~]# snmptranslate .1.3.6.1.2.1.4.20.1.1 -Of
.iso.org.dod.internet.mgmt.mib-2.ip.ipAddrTable.ipAddrEntry.ipAdEntAddr
Windows 8.1 以前、および Windows 10 が x86 である場合。
一応 Windows 版の NET-SNMP があるようです。こちら 。
インストールとか使い方の参考はこちら 。
tags: SNMP posted in SNMP , サーバー管理 by ooltcloud | No Comments
2017年12月17日
SNMP に関する基本的な用語のメモ。
標準 MIB と 拡張 MIB
MIB は大きく 2 つの領域に分かれています。
標準 MIB (.1.3.6.1.2.1 .iso.org.dod.internet.mgmt.mib-2)
標準 MIB (MIB-2) は主に機器共通で持っているであろう情報が登録されています。
例えば .iso.org.dod.internet.mgmt.mib-2.system.sysName (.1.3.6.1.2.1.1.5) でその機器の名前を、 .iso.org.dod.internet.mgmt.mib-2.ip.ipAddrTable.ipAddrEntry.ipAdEntAddr (.1.3.6.1.2.1.4.20.1.1) はその機器が持つ ip アドレスを取得することができます。(多分)
ただ、MIB-2 にあるデータが必ず各機器に存在するか?というとそうではなく例えば .iso.org.dod.internet.mgmt.mib-2.host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunName (.1.3.6.1.2.1.25.4.2.1.2) は Windows は実行プロセス名を列挙しますが、ScreenOS は「オブジェクトがない (=No Such Object available on this agent at this OID)」と戻します。(多分)
拡張 MIB (.1.3.6.1.4.1 .iso.org.dod.internet.private.enterprises)
拡張 MIB (enterprises) は主に機器固有の情報が集められています。
機器固有と言っても同じアドレス (OID 番号) で機器が違うと意味が違うのは困るので enterprises の直下は各ベンダーごとに番号が割り当てられていています。Windows のレジストリに例えると HKLM:\Software の直下はベンダー名になっているようなものです。なので異なるベンダーによるアドレス重複 (OID 番号の重複) はありません。逆に機器特有の情報を取得したい場合は、当該機器の MIB ファイルを取得しないと snmpwalk 等で取得したオブジェクトが何を示すのかわからない、ということでもあります。
例えば、77 と 311 は Microsoft が、2021 は NET-SNMP (ucdavis) が割り当てられています。
.1.3.6.1.4.1.77 iso.org.dod.internet.private.enterprises.lanmanager
.1.3.6.1.4.1.311 iso.org.dod.internet.private.enterprises.microsoft
.1.3.6.1.4.1.2021 iso.org.dod.internet.private.enterprises.ucdavis
OID 番号が手元にあるけど、MIB ファイルは手元にないのでそれが何かがわからない、という場合は http://oidref.com/ が便利です。oidref.com/ の次に OID 番号を入力すると何かを教えてくれます。以下は net-snmp の OID 番号を入れてみた例です。
http://oidref.com/1.3.6.1.4.1.2021
コミュニティ
名前の通りコミュニティでアクセス制御に使用します。例えば public だと特定の公開範囲で読み込みのみ、private だと全ての範囲で読み書き可能、みたいな設定をします。
しかしよく使用されている SNMP v2 はコミュニティ名指定以外の認証(パスワード等)がないので、コミュニティ名が知られるとアクセスし放題です。なのでコミュニティ名は類推しにくいユニークな名称にしたほうが良いと思われますが、大体のケースで public をそのまま使っているようです(汗
エージェントとマネージャー
エージェントが MIB を持っている側でありサーバー側です。監視対象(=機器)がエージェントになります。そして PC 等に設置されるマネージャーが MIB をアクセスするクライアント側です。
語感的にエージェントがクライアント側、マネージャーがサーバー側のように感じますが、MIB との関係だけでいえば語感とは逆なので注意です。
エージェントが部下、マネージャーが上司で、報告する元ネタ(=MIB)は部下が持っていて上司が適宜それを確認に行く、って感じですね。
tags: SNMP posted in SNMP , サーバー管理 by ooltcloud | No Comments
2017年12月17日
「SNMP を使えば周辺機器などの情報や状態を知ることができる」という程度の理解で SNMP を使ってみようと調べると OID とか MIB とかよくわからない用語に圧倒されました。たとえば MIB ツリーは以下のようなの図が提示されるわけですが、これがよくわからないのです。MIB-2 の OID が .1.3.6.1.2.1 だ、と言われてもサッパリなわけです(汗
iso(1) 階層1
│
org(3) 階層2
│
dod(6) 階層3
│
internet(1) 階層4
│
├────────────────────────────────────────────┬────
mgmt(2) private(4) 階層5
│ │
mib─2(1) enterprise(1) 階層6
│ │
┌─────────┬─────────┴──┬─────┬─────┬────────┬───────┬─── │
system(1) interface(2) at(3) ip(4) icmp(5) tcp(6) udp(7) │ 階層7
│
─┬────────┬──────────────┬─────────┬────────┴──────┬───
cisco(9) lanmanager(77) nec(119) microsoft(311) ucdavis(2021) 階層7
なのでもう少し平易な説明ができないものか?(特に Windows ユーザー向けに)と思ったのでまとめてみることにしました。
上記の MIB ツリー。Windows ユーザーにとって一番イメージしやすい近い存在というとレジストリエディタではないかと思います。
たとえば、Windows の場合コンピューター名を記録している場所は .iso.org.dod.internet.mgmt.mib-2.system.sysName.0 なので、レジストリエディタに模して見ると以下のような感じです。
Windows だとシンボルの区切りは \ (バックスラッシュまたは円記号) ですが、SMMP の場合 . (ドット) で区切ります。なので、
.iso.org.dod.internet.mgmt.mib-2.system.sysName.0
は Windows 的な表記だと
\iso\org\dod\internet\mgmt\mib-2\system\sysName\0
と等価です。ドットから始まる場合、ルートからの絶対パスであるのも考え方は同じです。
そして、このアドレス .iso.org.dod.internet.mgmt.mib-2.system.sysName.0 に格納されている値が "ComputerName.DomainName" (文字列値) であるというわけです。
レジストリと明らかに違うのは、SNMP のデータベースは上記のようなシンボルを文字列で管理してるのではなくて、OID (=オブジェクト ID) 番号で管理している点です。OID 番号で表すと上記のツリーは以下のようになります。
したがって、.iso.org.dod.internet.mgmt.mib-2.system.sysName.0 は .1.3.6.1.2.1.1.5.0 と表すことができます。というかこちらが真のアドレスです。これは IP アドレスとホスト名のような関係似ていて、真のアドレス (この場合は .1.3.6.1.2.1.1.5.0) に対して別名 (この場合は .iso.org.dod.internet.mgmt.mib-2.system.sysName.0) を付けて人が読みやすいようにしています。
それでは、IP アドレスとホスト名を対応付けている hosts のようなファイルが何か?というと、それが MIB ファイルです。
以下は MIBファイル "SNMPv2-SMI.txt" の一部です。このようなファイルで OID 番号に対して 名前を付けています。
(例えば org は "iso 3" なので .1.3、dod は "org 6" なので .1.3.6 といった感じです)
SNMPv2-SMI DEFINITIONS ::= BEGIN
-- the path to the root
org OBJECT IDENTIFIER ::= { iso 3 } -- "iso" = 1
dod OBJECT IDENTIFIER ::= { org 6 }
internet OBJECT IDENTIFIER ::= { dod 1 }
directory OBJECT IDENTIFIER ::= { internet 1 }
mgmt OBJECT IDENTIFIER ::= { internet 2 }
mib-2 OBJECT IDENTIFIER ::= { mgmt 1 }
transmission OBJECT IDENTIFIER ::= { mib-2 10 }
experimental OBJECT IDENTIFIER ::= { internet 3 }
private OBJECT IDENTIFIER ::= { internet 4 }
enterprises OBJECT IDENTIFIER ::= { private 1 }
従って .iso.org.dod.internet.mgmt.mib-2.system.sysName.0 という指定をしたい場合は MIB ファイルを適切に配置することが必要になります。対して .1.3.6.1.2.1.1.5.0 でアクセスする場合には MIB ファイルは必要ではありません。
そしてこのレジストリ全体に相当するデータベースのことを MIB (=Management Infomation Base) といいます。(したがって「MIB」と「MIB ファイル」は同じものではありません。)
tags: SNMP posted in SNMP , サーバー管理 by ooltcloud | No Comments
2017年12月9日
CentOS 7 での NTP Client の設定方法のメモ。
/etc/chrony.conf を編集します。
以下を入力します。
nano /etc/chrony.conf
編集前の chrony.conf。server から始まる設定を全部削除します
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst
# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift
編集後の chrony.conf。
xxx.xxx.xxx.xxx は同期したい時刻サーバーのアドレスです。(IP でも FQDN でもどちらでも可)
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server xxx.xxx.xxx.xxx iburst
# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift
chronyd を再起動します。
systemctl restart chronyd.service
更なる設定
ここがくわしそうです。> https://qiita.com/yunano/items/7883cf295f91f4ef716b
posted in Linux , OS , サーバー管理 , 時刻 by ooltcloud | No Comments
2017年12月8日
Oracle の インスタントクライアントのインストールのメモ。バージョンは 11.2 です。
今回は ODP.NET (.NET4系) と SQL*Plus をインストールしてみました。
ODAC112040Xcopy_32bit を ダウンロードします。
OTN のサイト (http://www.oracle.com/technetwork/database/windows/downloads/utilsoft-087491.html ) を参照し ODAC112040Xcopy_32bit.zip (ODAC 11.2 Release 6 (11.2.0.4.0) Download the XCopy version) を選択します。
ダウンロードした ODAC112040Xcopy_32bit.zip を適当なフォルダに展開します。ここでは展開先フォルダを C:\ORATEMP とします。
ODAC (Oracle Data Access Components for Windows) のインストールをします。
管理者モードでコマンドプロンプトを起動します。
カレントディレクトリを C:\ORATEMP (cd C:\ORATEMP) にしてから install と打ってみます。すると以下のように表示されます。
C> install
Usage:
install.bat component_name oracle_home_path oracle_home_name [install_dependents]
Example:
install.bat all C:\oracle myhome (install all components)
install.bat odp.net2 C:\oracle myhome true (install ODP.NET 2 and its dependent components)
install.bat odp.net4 C:\oracle myhome true (install ODP.NET 4 and its dependent components)
install.bat asp.net2 C:\oracle myhome true (install ASP.NET Providers 2 and its dependent components)
install.bat asp.net4 C:\oracle myhome true (install ASP.NET Providers 4 and its dependent components)
install.bat oledb C:\oracle myhome true (install OraOLEDB and its dependent components)
install.bat oo4o C:\oracle myhome true (install OO4O and its dependent components)
install.bat oramts C:\oracle myhome true (install ORAMTS and its dependent components)
install.bat basic C:\oracle myhome false (install Oracle Instant Client)
今回は odp.net4 をインストールするので以下のように入力します。
インストール先フォルダを C:\Oracle、Oracle Home の名前を odac112 としています。
install odp.net4 C:\Oracle\ odac112
instantclient-sqlplus-nt-11.2.0.4.0.zip を ダウンロードします。
OTN のサイト (http://www.oracle.com/technetwork/topics/winsoft-085727.html ) を参照し instantclient-sqlplus-nt-11.2.0.4.0.zip (Instant Client Package - SQL*Plus: Additional libraries and executable for running SQL*Plus with Instant Client) を選択します。
SQL*Plus のインストールをします。
ダウンロードした instantclient-sqlplus-nt-11.2.0.4.0.zip を解凍すると instantclient_11_2 というフォルダがあり、その中に sqlplus.exe 他のファイルがあります。このファイル群を上記で ODAC をインストールしたフォルダ (C:\Oracle) にコピーします。
コピーした結果、sqlplus.exe と adrci.exe が同じフォルダ (C:\Oracle) にあることを確認します。
レジストリに設定を追加します。
デフォルトだと SQL*plus のメッセージが英語なので、これを日本語に変更します。
Windows が 64bit 版の場合、レジストリエディタ等で HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Oracle\KEY_odac112 を開きます。(最後の KEY_ の後の文字列が Oracle Home の名称です)
Windows が 32bit 版の場合や 64bit 版 の Oracle Client をインストールした場合の場所は HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\KEY_odac112 です。(途中の WOW6432Node がありません)
開いた場所に以下の値を足します。
文字列値: NLS_LANG 値: Japanese_Japan.JA16SJISTILDE
文字列値: SQLPATH 値: C:\Oracle
これで SQL*plus が日本語表示になることを確認します。
また、C:\Oracle に login.sql を作成すると、ログイン時に読み込んで実行されます。(login.sql を作成し set linesize 300 とかをいれておくと便利)
起動の確認をします。
コマンドプロンプトを起動し、カレントディレクトリをインストールフォルダにします。(cd C:\Oracle)
ここで、sqlplus /nolog と打ち、起動できれば OK です。
ただ、この方法だと毎回カレントディレクトリをインストールフォルダにしてから実行する必要があるので、PATH を設定するなどをしたほうが良いですが、既存環境との干渉もあるかと思うので、そのあたりを配慮の上設定してください。
tnsnames.ora の設定
tnsnames.ora の設定がしたい場合はインストールディレクトリの下の network\admin (C:\Oracle\network\admin) に設置します。tnsname.ora のサンプルファイルは sample フォルダ (C:\Oracle\network\admin\sample) にあります。
または、TNS_ADMIN 環境変数 (または上記 NLS_LANG を設定したレジストリキーに TNS_ADMIN 値) に tnsnames.ora を設置するフォルダ名を設定します。
posted in Oracle , OS , Windows , データベース by ooltcloud | 1 Comment
2017年12月8日
CentOS 7 minimal に Oracle Database XE 11gR2 をインストールする場合の手順のメモ。
主にここの手順をみて行いましたので、より詳しい解説はそちらへ。
http://www.ajisaba.net/db/ora_linux_install.html
Oracle XE をダウンロードします。
OTN のダウンロードサイト (http://www.oracle.com/technetwork/jp/database/database-technologies/express-edition/downloads/index.html ) から Oracle Database Express Edition 11g Release 2 for Linux x64 を選択し oracle-xe-11.2.0-1.0.x86_64.rpm.zip をダウンロードします。
CentOS 7 minimal のインストールをします。
CentOS minimal 自体のインストール方法はこちらを参照してください。 (http://ooltcloud.sakura.ne.jp/blog/201711/article_30210409.html )
CentOS 7.4 インストール直後, メインメモリ 1GB 環境で Oracle Database XE 11.2 はインストール出来ましたが、環境によってはメモリ不足などでインストール出来ない場合があるので注意してください。
インストールした CennOS に SSH を使って root でログインします。
ダウンロードした oracle-xe-11.2.0-1.0.x86_64.rpm.zip を /tmp に SSH-SCP で転送しておきます。
インストールに必要なパッケージのインストールをします。
yum install unzip
yum install bc
yum install nano
bc は計算式(?)を渡すと答えを戻してくるようなコマンドのようです。Oracle のインストーラーか使っているようなので用意しておきます。bc 自体の使用例は以下のような感じです。
echo "1+2+3" | bc
6
nano はエディタです。(個人的な好みです。お好みに応じて emacs とかどうぞ)
oracle-xe-11.2.0-1.0.x86_64.rpm.zip を /tmp に解凍します。
cd /tmp
unzip oracle-xe-11.2.0-1.0.x86_64.rpm.zip
/tmp/Disk1 をカレントにして、解凍された rpm をインストールします。
cd /tmp/Disk1
rpm -ivh oracle-xe-11.2.0-1.0.x86_64.rpm
インストールが完了したら /etc/init.d/oracle-xe configure を実行し、初期化を行います。
例えば以下のような感じで入力します。(網掛部分)
また、netstat でエラーが出ていますが問題なさそうなので無視しています。(そのかわり Listen ポートが被らないように設定します。使用ポートは ss コマンドで確認します。)
エラーが気になる人は netstat をインストール (yum install net-tools) してから以下の初期化を実行してください。
[root@localhost ~]# /etc/init.d/oracle-xe configure
Oracle Database 11g Express Edition Configuration
-------------------------------------------------
This will configure on-boot properties of Oracle Database 11g Express
Edition. The following questions will determine whether the database should
be starting upon system boot, the ports it will use, and the passwords that
will be used for database accounts. Press to accept the defaults.
Ctrl-C will abort.
Specify the HTTP port that will be used for Oracle Application Express [8080]: 8080
/etc/init.d/oracle-xe: line 362: netstat: command not found
Specify a port that will be used for the database listener [1521]: 1521
/etc/init.d/oracle-xe: line 405: netstat: command not found
Specify a password to be used for database accounts. Note that the same
password will be used for SYS and SYSTEM. Oracle recommends the use of
different passwords for each database account. This can be done after
initial configuration: (管理者用のパスワード)
Confirm the password: (管理者用のパスワード)
Do you want Oracle Database 11g Express Edition to be started on boot (y/n) [y]: y
Starting Oracle Net Listener...Done
Configuring database...Done
Starting Oracle Database 11g Express Edition instance...Done
Installation completed successfully.
最後に Installation completed successfully. が出ていれば成功です。
sqlplus 用に rlwrap をインストールします。
標準の状態だと sqlplus でカーソルキーを使った操作ができないので rlwrap というラッパーを導入します。
詳しくはここを参照して下さい。 https://qiita.com/inomasa/items/391c025532db6b87a1d5
rlwrap は 公式リポジトリにはないパッケージらしく、epel リポジトリを参照する必要があるらしいです。なので、まずは epel リポジトリを参照できるようにします。
epel についてはここを参照しました。http://note.kurodigi.com/centos7-epel/
yum install epel-release.noarch
デフォルトの設定だと公式リポジトリにあるパッケージも epel から取得するようになるらしいので、設定を変更し普段は epel を参照しないようにしておきます。
nano /etc/yum.repos.d/epel.repo
[epel] ブロックにある enabled を 0 にします。
[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch
failovermethod=priority
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
rlwrap をインストールします。上記の設定で epel を参照しない設定にしたので、--enablerepo=epel オプションを付加して epel リポジトリを参照するように指定してインストールします。
yum install --enablerepo=epel rlwrap
環境設定をします。
Oracle ユーザーでログインし、.bash_profile, .bashrc の設定をします。
Oracle のインストールで作成された oracle ユーザーには、.bash_profile, .bashrc がないらしいので、ひな形フォルダ (/etc/skel/) から .bash_profile, .bashrc をコピーしてから行います。
su - oracle
cp /etc/skel/.bash_profile /u01/app/oracle/
cp /etc/skel/.bashrc /u01/app/oracle/
nano ~/.bashrc
.bashrc の内容を以下のように変更します。
先頭の . (ドット) は忘れないように。これがないとスクリプト内で設定した環境変数が設定されません。(言い回しが難しい -_-;)
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
. /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh
Oracle への接続の確認をします。
一旦 root に戻り、その後 oracle ユーザーで再接続してから oracle への接続を確認します。
[oracle@localhost root]$ rlwrap sqlplus / as sysdba
SQL*Plus: Release 11.2.0.2.0 Production on 金 12月 8 00:00:00 2017
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
に接続されました。
SQL> select status from v$instance;
STATUS
------------
OPEN
SQL>
sqlplus の前に rlwrap を書かないと、カーソルキーを操作したとき謎の文字が表示されるので注意します。
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
に接続されました。
SQL> ^[[A
面倒くさい、と思うようであれば .bashrc に alias を設定してください。
alias sqlplus='rlwrap sqlplus'
外部からの接続確認をします。
外部から接続する場合にはファイアウォールを適切な設定にします。今回は面倒なので停止にします。
systemctl stop firewalld
systemctl disable firewalld
これで、外部からの接続に成功すれば OK です。
以下は Windows のコマンドプロンプトからの接続の例です。
C>sqlplus sys/管理者用のパスワード@xxx.xxx.xxx.xxx/xe as sysdba
SQL*Plus: Release 12.1.0.1.0 Production on 金 12月 8 20:59:15 2017
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
に接続されました。
SQL>
posted in Linux , Oracle , OS , サーバー管理 , データベース by ooltcloud | No Comments
2017年12月3日
Hinemos 6 になると Windows 版の Manager がリリースされるという話だったので期待して待っていたのですが、Windows 版はサブスクリプション契約のみの提供で、契約がない場合は試用版すら提供されないという話のようなので、あきらめて Linux 版のインストールをしてみました。以下はその際のメモ。
Hinemos のインストールは http://www.hinemos.info/technology/nttdata/2017033001 を参考にして作業しています。なので詳しい解説はリンク先を参照してください。
ただ、上記の手順では hinemos_change_listen_address.sh の話がでてこないので、本件については http://d.hatena.ne.jp/hinemos_dev/20170206 を参照しています。(JDK の不具合が原因らしいので、最近の JDK をインストールしていれば問題は発生しないのかもしれません)
Cent OS 7 をインストールします
Cent OS 7 のインストールは以下を参照してください。
SSH で接続します。
ローカルコンソールから作業しないように。インストール後の Hinemos が日本語表示になりません。
SSH で接続した場合も、locale が日本語になっていることを確認します。
適当に文字を打って、日本語のエラーメッセージが戻れば OK です。
以下は aaaa と打ってエラーを出し、メッセージが日本語であることを確認した例。
まず、Hinemos のインストールに必要なパッケージ類をインストールします。(nano をインストールしているのは個人的な好みです)
yum install nano
yum install unzip
yum install vim-common
yum install java-1.8.0-openjdk
yum install wget
github から Hinemos 6 の Manager と Web Client の rpm を /tmp にダウンロードします。
cd /tmp
wget https://github.com/hinemos/hinemos/releases/download/v6.0.0/hinemos-6.0-manager-6.0.0-1.el7.x86_64.rpm
wget https://github.com/hinemos/hinemos/releases/download/v6.0.0/hinemos-6.0-web-6.0.0-1.el7.x86_64.rpm
SELinux を無効にします。
Hinemos は SELinux が無効でないとインストールできません。
getenforce と入力して Enforcing と表示される場合、SELinux は有効なので無効にします。
nano /etc/selinux/config
SELinux の項目が enforrcing となっているので、
disabled に変更します。
CTRL+X で変更を保存し、再起動します。
reboot
再起動後 getenforce と入力して Disabled と表示されれば OK です。
Manager と Web Client をインストールします。
cd /tmp
rpm -ivh hinemos-6.0-manager-6.0.0-1.el7.x86_64.rpm
rpm -ivh hinemos-6.0-web-6.0.0-1.el7.x86_64.rpm
Manager と Web Client を起動します。
service hinemos_manager start
service hinemos_web start
listen アドレスの変更をします。
たとえば、manager をインストールしたサーバーの IP アドレスが 192.168.0.1 である場合は以下のようにします。
http://d.hatena.ne.jp/hinemos_dev/20170206
service hinemos_manager stop
service hinemos_pg start
cd /opt/hinemos/sbin/mng
./hinemos_change_listen_address.sh 192.168.0.1
service hinemos_pg stop
service hinemos_manager start
ss -ao を実行し、port 8080 の待ち受けが 127.0.0.1 ではなく 192.168.0.1 であれば OK です。
ss -ao | grep tproxy
tcp LISTEN 0 50 ::ffff:192.168.0.1 :tproxy :::*
面倒なのでファイアウォールを止めます。(良い子は正しく必要なポートのみを開けるようにしましょう)
systemctl stop firewalld
systemctl disable firewalld
Web Client への接続を確認します。
webclient をインストールしたサーバーに接続します。
その際、接続先 URL が ループバックアドレス (127.0.0.1) の場合は、上記で設定した listen アドレスに変更します。
127.0.0.1 となっている場合は、
192.168.0.1 に変更します。(パスワードも入力します)
ログインできれば完了です。
posted in Hinemos , Linux , OS , サーバー管理 by ooltcloud | No Comments
2017年12月2日
posted in Linux , OS by ooltcloud | No Comments
2017年12月1日
ちょっと気になったので QR コードの符号化方式について調べてみたのでメモ。
けれども、以下に書くことは不正確なので注意。正しく知りたい場合は JIS X 0510 を当たるなどしてください。
発端は「QR コードは Shift-JIS で記録している」という記述をどこかで見たこと。で、実際のところどうなのだろう?とか思って調べてみた。
結論としては、QR コードの符号化方式は、数字, 英数字, 漢字, バイト列 の 4 つのモードがあるらしい。
以下、それぞれの大雑把 (= つまり甚だ正確ではない) にどういうことをしているかまとめる。
数字モード
10 進数 3 桁を 10 bit で表現する。
1000 通り < 1024 (2^10) ということ。
英数字モード
数字、英大文字および記号、計 45 字 2 桁を 11 bit で表現する。
45^2 = 2025 通り < 2048 (2^11) ということ。
漢字モード
Shift-JIS 領域 (JIS X 0208) の文字 1 桁を 13 bit で表現する。
JIS 第 1 水準 + 第 2 水準 + 非漢字 で 6,879 文字らしいから、8192 (2^13) で入るということで。
バイトモード
8bit を表現。
漢字モードでは Shift-JIS コードをもとに計算しますよ、ということらしいので「Shift-JIS で記録」と称している模様。なので Shift-JIS のコードそのものが記録されているわけではない点に注意。
もっともどんなコードで記録されているかを意識する必要はないかとは思います。それよりは記録される文字の範囲は気にしておく必要がありそうです。
それよりも残るバイトモードとは何なのか。
以下のようなものが入るらしい。
漢字モードで入れることのできなかった領域の Shift-JIS 文字
Unicode 他 Shift-JIS 以外のエンコード方式の文字
英小文字
バイトモードというからバイトストリーム的なものが入るのかとおもったら、そういうことではなくて、基本は他のモードで入れられなかった文字がここに入る、といった趣の模様。
しかしそうすると、このバイトモードに格納されている文字の文字コードは何? ということになるわけですが、しかしエンコード方式を QR コード内に記録するところはなさそうなので、アプリケーション側でよしなに…、ということっぽい。 ( よく調べてないので違うかもしれませんが )
もちろんアプリケーション固有で解釈できる、ということはバイトストリーム的な扱いも可能なわけですが。
とはいえ、この領域は多くは QR リーダー内で処理されているでしょうから手が出ない気がしますが… ( 実際はどうなのでしょう? )
JSON や XML のような文書構造もなさそうなので、必要であればアプリケーション側で実装、ですね。
調べた感想としては、3桁まとめて符号化して容量を減らす、などのアイデアが面白いな、よく考えられているな、って感じでした。
あと、ASCII 領域である英小文字がバイトモードの領域 (= 符号化方式不明な領域 ) にしか入らない、って点も意外でした。
posted in ハードウェア by ooltcloud | No Comments
2017年12月1日
Powershell を使って WMI オフジェクトと対話的にたわむれる方法のメモ。
WMI クラスの一覧を表示
Get-WmiObject -List
指定した WMI クラスのプロパティの一覧を表示
# Win32_OperatingSystem クラスの場合
(Get-WmiObject -List Win32_OperatingSystem).Properties | select Name
指定した WMI オブジェクトの値を表示
# Win32_OperatingSystem オブジェクトの場合
Get-WmiObject Win32_OperatingSystem | select *
WQL (WMI Query Language) を使用した検索
# Win32_OperatingSystem オブジェクトの、Caption, OSArchitecture, BuildNumber, Version, CSDVersion を取得したい場合
$q = "
select
Caption,
OSArchitecture,
BuildNumber,
Version,
CSDVersion
from
Win32_OperatingSystem
"
Get-WmiObject -Query $q
参考文献など
posted in OS , PowerShell , Windows , WMI by ooltcloud | No Comments
2017年11月30日
Windows ではキーボードから直接、IME に頼らず文字コードを入力することができます。
基本的な操作は、[ALT] キーを押し込んだままテンキーで文字コードを入力し [ALT] キーを離します。
たとえばメモ帳で、[ALT] を押す → [3] → [3] → [4] → [4] → [0] → [ALT] を離す、とすると「あ」が入力できます。33440 は「あ」の Shift-JIS における文字コード (82A0h = 33440) です。
さて問題はここからです。
メモ帳ではなく Wordpad で「あ」を入力したいとします。
ところがメモ帳と同じように、[ALT] を押す → [3] → [3] → [4] → [4] → [0] → [ALT] を離す、としても意図した文字は入力できません。「芠」と謎の文字が入力されます。
そこで Wordpad の場合は、[ALT] を押す → [1] → [2] → [3] → [5] → [4] → [ALT] を離す、とします。すると「あ」が入力されます。なぜかというと、12354 というのは「あ」の Unicode における文字コード (U+3042 = 12354) だからです。
つまりこの「[ALT] キーを押し込んだまま文字コードを入れる」という操作は、それを受け取るアプリケーションによって挙動が異なるということです(汗
メモ帳や Excel は Shift-JIS 派、Microsoft Word, Wordpad, Outlook は Unicode 派です。Microsoft Edge に至っては、下位 8bit を Shift-JIS で評価します。 (つまり 177 も 433 も共に「ア」と評価されます)
Microsoft Word と Wordpad は同じかと思えばそうでもなく、例えば 177 の場合、Microsoft Word では「ア」ですが、Wordpad (Windows 8 系以前) では「±」だったりします。Wordpad のほうがより Unicode に忠実ですね。Microsoft Word のほうは 8bit 領域は Shift-JIS で判断し、それ以上は Unicode で判断といった感じです。とはいえ、Windows 10 の Wordpad では Microsoft Word と同じく「ア」だったりします(汗
また、Windows Form (VB や C#) の場合、TextBox コントロールは Shift-JIS 派、RichTextBox コントロールは Unicode 派です。つまりこの両方のコントロールを使用したアプリケーションが存在すると、同一アプリケーション内の入力の場所ごとに違う評価がされることになります。
とにかく重要なことは、この IME を経由しない文字コード入力というのは、受け取るアプリケーションやコントロールによって挙動が異なる、ということです。
なので例えば QR リーダーのようなデバイスで、キーボードエミュレーション (HID 接続) を行う場合、ASCII 領域以外の文字は何が入ってくるかわからないということです。従って、キーボードエミュレーションで ASCII 領域以外の文字を入力させたい場合、上記のような傾向はあるものの確実ではないので、アプリケーションごと、入力場所毎に意図した入力ができるかどうかを検証しておく必要があります。
posted in OS , Windows by ooltcloud | No Comments
2017年11月30日
posted in Linux , OS by ooltcloud | No Comments
2017年11月18日
以下な感じで。
PS> (Get-Item "hklm:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue("ReleaseId")
1703
ポイントは、キーの部分 (上記だと Get-Item にかかる部分) と値 (上記だと .GetValue にかかる部分) を分けて書くところでしょうか。(一括で書けない)
posted in OS , PowerShell , Windows by ooltcloud | No Comments
2017年11月14日
CTRL + 6 を押してみましょう。たぶんあなたは "&" を打とうとして SHIFT ではなく CTRL を押しました(汗
GUI で直す場合は以下で。
この「オブジェクトの表示」が「なし」になっているときは、グラフや画像等、いわゆる「オブジェクト」の類が全て非表示になります。
また、新たな画像の貼り付けやグラフの挿入もできなくなっていますから、そのようなことが起こった場合は、当該機能で非表示にされていないかを確認します。
posted in Excel , Office by ooltcloud | No Comments
2017年11月10日
結論から書くとこんな感じです。(Windows)
type test.sql | sqlplus -s / as sysdba
つまり、sql ファイルの内容をパイプで sqlplus に渡してやります。
教科書通りだと、sqlplus -s / as sysdba @test.sql なのですが、これだと exit のない sql ファイルだと sqlplus 内の入力待ちで止まってしまいます。かといって、sql ファイルに exit を足すと、sqlplus を対話的に使っているときにその sql ファイルをSQL> @test.sql な感じで呼び出すと sqlplus を exit してしまうので(汗
posted in Oracle , データベース by ooltcloud | No Comments
2017年11月6日
Oracle の表領域の使用量と空き容量を知る方法について、OEMDC(Oracle Enterprise Manager Database Console)や SI Object Browser などのツールを使って確認するのは容易ですが、SQL*Plus で確認する方法がわからないのことが多いので、その方法のメモ。
まず大前提として「表領域の現在容量や空き容量という情報はない」です。あるのは「表領域に属する "データファイル" のサイズと空き容量」です。
さらにはデータファイルについても「現在使用量」という情報はないです。データファイルの現在使用量はデータファイルのサイズから空き容量を差し引いて求めます。
それを踏まえたうえで、例えば USERS 表領域の使用量を求めるには以下のように求めます。
USERS 表領域に属するデータファイルごとのサイズを表示します。
select FILE_ID, BYTES, FILE_NAME from DBA_DATA_FILES where TABLESPACE_NAME='USERS';
USERS 表領域に属するデータファイルごとの空き領域を表示します。
select FILE_ID, BYTES from DBA_FREE_SPACE where TABLESPACE_NAME='USERS';
これらの合計の差が使用量になりますが、ファイル毎に表示されて面倒なのと、単位が Byte で桁が無駄に多いので、集計して MB で表示します。
select sum(BYTES) / (1024*1024) from DBA_DATA_FILES where TABLESPACE_NAME='USERS'; --①
select sum(BYTES) / (1024*1024) from DBA_FREE_SPACE where TABLESPACE_NAME='USERS'; --②
上記で出た数値を差し引けば(①-②)、現在の使用量が求められます。
表領域ごとに使用量と使用率の一覧が出る…みたいな SQL が欲しい場合は、上記をヒントに自分で作るか、他の色んなサイトで紹介されているのでそちらをどうぞ(汗
また余談ですが、上記のように迂遠な方法を使わずとも、以下の view を用いて表示する方法もあります。
select * from DBA_TABLESPACE_USAGE_METRICS where TABLESPACE_NAME='USERS';
これの注意点としては、表示される数値はブロック数(ブロックサイズは show parameter db_block_size で参照)でありバイトではない点と、AUTOEXTEND ON を指定している場合は、現在のデータベースファイルのサイズではなく、理論上の最大(ディスク容量またはデータベースファイルの最大拡張サイズ)が表示される点です。特性を理解したうえで使い分けてください。
posted in Oracle , データベース by ooltcloud | No Comments
2017年7月1日
VB.NET で JSON を使ったシリアライズ/デシリアライズの例。
Json.DataContractJsonSerializer は .net 4 系で追加されたようなので、.net 2 系では動作しません。
ポイントは、シリアライズ対象のクラスに <DataContract> 属性をつけること、シリアライズ対象のメンバーに<DataMember> 属性をつけることだろうか。
' 参照設定 "System.Runtime.Serialization"
Imports System.IO
Imports System.Text
Imports System.Runtime.Serialization
<DataContract>
Public Class Container
<DataMember>
Public Items As New Dictionary(Of String, Object)
End Class
Module Module1
Sub Main()
' 元のオブジェクトの作成
Dim obj0 = New Container
obj0.Items.Add("AAA", 100)
obj0.Items.Add("BBB", 250)
'シリアライザー
Dim serializer = New Json.DataContractJsonSerializer(GetType(Container))
' シリアライズ
Dim str1 As String = ""
Using mem = New MemoryStream()
serializer.WriteObject(mem, obj0)
str1 = Encoding.UTF8.GetString(mem.ToArray())
End Using
' デシリアライズ
Dim obj2 As Container
Using mem = New MemoryStream(Encoding.UTF8.GetBytes(str1))
obj2 = CType(serializer.ReadObject(mem), Container)
End Using
End Sub
End Module
posted in Program , VB.NET by ooltcloud | No Comments
2017年6月23日
posted in OS , Windows by ooltcloud | No Comments
2017年6月11日
Windows にはメッセージを通知する msg.exe がありますが、これを使って他のコンピューターに通知を行う場合、受信側のファイアウォールの設定が必要です。
win+r を押し「ファイル名を指定して実行」を呼び出す
wf.msc を入力し「セキュリティが強化された Windows ファイアウォール」を呼び出す
左ペインの「受信の規則」を選択する
リモートサービス管理(NP受信)を選択する
「有効」と「接続を許可する」をチェック
posted in OS , Windows , 環境設定 by ooltcloud | No Comments
2017年6月11日
先日こんなツイートがありました。
もちろんこれは大笑いするところですし、して良いのですが。他方「なぜ電卓で検算するのか」という点、すなわち「Excel よりも電卓のほうが信用できる」という点について理解したうえで笑ってない人も多い印象を受けたので、補足がてら以下に記す(ぇ
例えば Excel で集計した場合、以下のようなことが起こります。
小計を合計すれば ¥2,980 のはずですが、Excel での計算結果は ¥2,981 になってしまっています。
なぜこのようなことが起こるかというと、表示形式で通貨にした時に、小数点以下は四捨五入で切り落としてしまう設定にしたからです。(デフォルト)
実際、銭単位の請求は一般にはしないので円で丸めるのは正解です。しかし上記の例では表示でまるめられているだけであって、あくまで合計は ¥2,981 ではなく ¥2,980.8 なんですね。
さて、ここまで踏まえたうえで。
いや、小数点以下をどうかしたいという話だったらちゃんと ROUND 関数を使うなり処理すればいいのでは?という話になるのですが。しかし、今しているのは検算の話です。ワークシート本体で ROUND 関数を使うことは否定していないわけです。むしろちゃんと ROUND 関数を使ったりして合計が一致することを「検算」しようとしているわけです。
そして「検算」という作業で。上記のような「みためは小数点以下はないけど実際には小数点以下の値があり、合計等の計算をすると、見た目の合計と真値の合計が不一致が発生する」系の検算って。Excel で出来ます?といったときに「こうすれば簡単にできるよ」と提案できる人は少数ではないかと思うわけです。
かくて、Excel で主たる計算をした後電卓で検算する、ということが起こるわけです。
検算するにしても Excel ですればいいじゃん?って話ではありますが、Excel だとセルの値をコピペしてしまうと同じ話が発生しますし「どのセルとどのセルを合計すれば?」という話になると、結局人の目に依存する話になってしまいます。かくて電卓が最適解になったりします。
で、これを自動で検算させようとすると「どのセルをどうやって合計をしようとして」「そしてその正解はこうだ」的な人間の判断が必要でして、まさに AI を駆使した仕事になるわけです。 (ちなみに Excel 内の計算式は間違っている可能性があるので、それを元に検算することはできません。人は Excel の計算式を参照して検算しませんよね。)
これが「これからはAIの時代だからお前らの仕事なんかなくなるんだぞ!」につながっているんだと思うので、深いツイートだな、とか思った次第(汗
posted in Excel , Office by ooltcloud | No Comments
2017年6月11日
この記事はポエム記事です(汗
個人的な偏見と恐らくは不正確な事実認識から書かれています。その点に注意して読み進めてください。
前提
SI 案件 (=受託開発) の現場を想定
アジャイル開発の対義はウォーターフォール開発であると仮定
結論
モノを買う以上「機能と予算と期間」はセットであり、これらが強固に結びついている以上、(受託開発では) アジャイル開発は成り立たない。
考察
所謂受託開発や SI と呼ばれているものは、前述の「機能と予算と期間」が全て固定されたうえで契約されることがほとんどであり、また多少の細分化やフェーズ分けは行われたとしても、分けた単位ではやはり固定される。この点でアジャイル開発は適さないと考えている。
こう書くと「それは契約の問題であり開発手法の問題ではない」という話になりがちなのだが、実際その指摘は一面的には真であると思う。しかし契約の形態が開発手法に影響を与えるのは当然であることに加え、開発手法の都合から契約を変更することはほぼ絶望的である。従って開発手法は契約に対して一方向的に従属する関係にあると言える。このため、開発手法の選択によって契約のありかたを考えないといけないなら「それは契約の問題であり開発手法の問題ではない」ということにはならない。ところがアジャイル開発が語られるうえで契約の問題はあまり話題に上ることはなく、そのあたりが齟齬や欺瞞、誤解や適合のむずかしさを生み出してしまっている源泉なのではないかと思っている。
では逆にアジャイル開発が有効である場合は何か。それは開発チームが「機能と予算と期間」を可変させる権限を持っている場合ではないかと考えている。つまり開発を外部に委託するのではなく、内部で開発を行うケースである。これは「比較的小規模なベンチャーのようなチームが自己が提供するサービスを開発するケース」などが該当するのではないかと思う。
しかし自己のサービスを開発する場合でも、規模が大きくなると組織の壁によって阻まれる。例えばリリース予定の機能がリリース予定の期日にリリースされることが確約できないと営業活動がむずかしいという問題がある。営業の視点では、予定された機能のリリースの期日がずれる、あるいはなくなるといったことは顧客に説明がつかなくなるので好まれない。従ってこのような力が働くとき、開発チームに対して「機能と期間」は確実に固定される。予算だけはその気になれば変動可能、というか嫌でも変動するが、しかし多くの場合は良い意味で変動することはない。
結局は外部に向けてはウォーターフォール的な表現、内部においては許容できる範囲でアジャイル的な取り組み、というのが現状の精一杯ではないかと思う。
また、この場合の「アジャイル的な取り組み」というのは、例えば 3 つのモジュールを作る場合に、純粋なウォーターフォール的な計画だと「設計→設計→設計→製造→製造→製造→テスト→テスト→テスト」みたいになるものを「設計→製造→テスト」× 3、みたいな感じにすることだと思ってる。つまり「動くソフトウェアを作る」ことを重視する。ただ、これも「許容できる範囲」と述べたように全てではなく、前半に設計だけで固めないとならない領域(DBの設計とか)はあるし、前述の「設計→製造→テスト」も「設計は上位のスキルが必要だ」「製造は打ち込み要素が大きくスキルが低くても構わない」「テストは当該の製造者ではない人あるいはそもそもプログラマではない人にやらせたい」などの要件、つまり人員配置の問題が絡むと、どうしてもアジャイル的なものにならない。
この大枠ウォーターフォールなものに、ところどころ「アジャイル」的な何かを持ち込むめること、それがアジャイルのメリットだ、というならそれはメリットかもしれない。しかし実際のところ、そのレベルではアジャイル開発の登場以前からアジャイル的なものはやっていた。ただそれは「その部分はその方法が適当だったのでそうした」というだけの話である。例えばプロトタイプ開発はアジャイル開発よりも前からあり、必要があればその手法を用いることはあった。プロトタイプ開発とアジャイルは現在は違うとされているけれども「必要なものから優先的に、動くものをリリースしていく」という観点からは類似している。違うことは「顧客(特にそのサービスを使うエンドユーザー)のところまで供給されているかどうか」であって、プロトタイプ開発だって開発チーム内や顧客(元請や発注主)に対しては見せていた。だから手法としての差はあまりないと思う。それがプロトタイプコードがリリースコードであり供給相手がエンドユーザーまで延びたからアジャイルだ、といわれるのは個人的には違和感がある。
また、アジャイルは雇用的なアプローチという見方もできる。つまり負荷の変動に弱い。時間あたりの処理量を固定して負荷を平準化し、総処理量の増加は時間方向に延ばす手法なのでそうなるのは当然ではある。
これは例えば「初期開発では多くのリソースが必要だが、保守フェーズにはいると初期開発ほどのリソースは必要ない」というケースに対応し辛い。下手すると保守フェーズに入っても初期開発で抱えたリソース(つまり人)の雇用を維持し続ける必要がでてしまう。この問題に対する解が「受託開発」である以上、初期開発と保守フェーズの負荷を均すという対策はありえない。
海外のことはまるで知らないが、恐らく海外では初期開発を行うに必要なリソースを雇用の後、初期開発が終了すると不要になるリソース分の雇用を切っているはずである。そうすれば「内部で開発」しつつ「必要な負荷」のコントロールができる。しかし現在の日本の雇用法制でこれができるか?というと疑問である。
この点も、一般にアジャイル開発の説明では「チームの人数」に言及はあっても「プロジェクト全体におけるチームの数(や総人口)」に言及されることが少ない点が、誤謬を生み出している原因の一つだと思っている。
というのが私の足りない頭で考えた現状であり、ウォーターフォールの「全ての WBS はプロジェクト開始前に計画されてなくてはならない」的な課題に対して脳内ドン・キホーテをやらかして百戦百敗した結果なのである。
アジャイル開発のメリットに目を奪われそれを適用しようとしても、そうすると全体のバランスを崩してしまい結局はウォーターフォール的な安定に戻る。その繰り返しである。かつてメリットに見えたものはまやかしでしかないように感じている。
ではウォーターフォールだと前述が解決できるのかというと出来ない。しかしウォーターフォールがアジャイル開発と大きく違い、かつ絶対的な利点は少なくとも「機能と予算と期間」にコミットできるという点にある。この差は大きい。それが例え「夢の計画」であっても・・・(汗
つまりこの「機能と予算と期間」にどうコミットするか、この最初にして相当に高いハードルを超えないことには、アジャイル開発のメリットなど何一つ考えられない状況なのである。
なので、誰かその方法を教えてください。もっともこれを超えられたとしても他にも問題は山積みだと思ってはいるが…(汗
posted in マネジメント , 与太話 by ooltcloud | No Comments
2017年4月18日
サーバー側 tcp ポート 8000 番を使ってリモートプロシージャコールを行ってみた例のメモ。
3つのプロジェクトを作ります。
RemoteClass プロジェクト (呼び出される処理)
RemoteServer プロジェクト (待ち受けをするサーバープロセス)
RemoteClient プロジェクト (呼び出す側のプロセス)
コード例は以下。詳細な説明は割愛(ぇ
RemoteClass プロジェクトの内容
Public Class RemoteClass
Inherits MarshalByRefObject
Private Shared _count As Integer
Public Function Method1(a As Integer) As Integer
RemoteClass._count += a
Console.WriteLine("Server side output: {0}", _count.ToString)
Return _count
End Function
End Class
RemoteServer プロジェクトの内容。
(RemoteClass プロジェクトと System.Runtime.Remoting を参照し、ルート名前空間の名前を同じ名前にします)
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Module Module1
Sub Main()
ChannelServices.RegisterChannel(New TcpChannel(8000), False)
RemotingConfiguration.RegisterWellKnownServiceType(
GetType(RemoteClass),
"MyAPP",
WellKnownObjectMode.SingleCall)
Console.WriteLine("Server Start")
Console.ReadLine()
Console.WriteLine("Server Stop")
End Sub
End Module
RemoteClient プロジェクトの内容。
(RemoteClass プロジェクトと System.Runtime.Remoting を参照し、ルート名前空間の名前を同じ名前にします)
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Module Module1
Sub Main()
ChannelServices.RegisterChannel(New TcpChannel(), False)
Dim remoteClass = CType(Activator.GetObject(GetType(RemoteClass),
"tcp://localhost:8000/MyApp"),
RemoteClass)
Dim result = remoteClass.Method1(1)
Console.WriteLine("Client side output {0}", result)
Console.ReadLine()
End Sub
End Module
posted in Program , VB.NET by ooltcloud | No Comments
2017年4月17日
かつてターミナルとかコンソールの時代は、テキストの装飾というと色指定か色反転 (=Inverse) か点滅かのいずれかしかなかったわけですが。
HTML にしても XAML にしても、色指定は Foreground で、色反転相当は Background でなんとかなるわけですが、なぜか点滅が難易度高いんですよね… html はかつて netscape navigator とやらではイケたらしいですが…?
ともかく、WPF XAML で点滅させる方法を考えてみました。以下はそのコード。
<StackPanel>
<StackPanel.Resources>
<!-- 点滅のためのストーリーボードの作成 -->
<Storyboard x:Key="BlinkingStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
RepeatBehavior="Forever">
<DiscreteDoubleKeyFrame KeyTime="0"
Value="0" />
<DiscreteDoubleKeyFrame KeyTime="0:0:0.5"
Value="1" />
<DiscreteDoubleKeyFrame KeyTime="0:0:2"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<!-- 点滅のためのスタイルの作成 -->
<Style TargetType="TextBlock"
x:Key="BlinkingStyle">
<Style.Triggers>
<Trigger Property="IsEnabled"
Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource BlinkingStoryboard}"
x:Name="BlinkingStoryboard1" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="BlinkingStoryboard1" />
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<!-- 点滅対象のテキスト -->
<TextBlock x:Name="Text1"
Text="点滅するテキスト"
Style="{StaticResource BlinkingStyle}"
IsEnabled="False" />
<!-- 点滅/点灯を切り替えるためのボタン -->
<StackPanel Orientation="Horizontal">
<Button Content="点滅"
Width="50"
Click="StartBlinkingClick" />
<Button Content="点灯"
Width="50"
Click="StopBlinkingClick" />
</StackPanel>
</StackPanel>
コードビハインド側はこんな感じ。
Private Sub StartBlinkingClick(sender As Object, e As RoutedEventArgs)
Me.Text1.IsEnabled = True
End Sub
Private Sub StopBlinkingClick(sender As Object, e As RoutedEventArgs)
Me.Text1.IsEnabled = False
End Sub
やっていることは以下のような感じ。
storyborad を使って、点滅のためのシーケンスを作ります。上記では UIElement の Opacity を 0.5 秒間 0% (=消去)、1.5 秒間 100% (=表示) することで点滅を表現しています。
その storyborad を textblock の style に適用。上記では IsEnabled の True で storyborad を開始、False で停止しています。
上記 2 つは resources 内に記述し、それぞれ名前をつけます。(x:Key="BlinkingStoryboard", x:Key="BlinkingStyle")
また、storyboard を停止するとき、開始した storyborad のインスタンスを指定しなくてはならないので、storyborad のインスタンスに名前をつけています。(x:Name="BlinkingStoryboard1")
その後 textblock にこの style を適用します。(Style="{StaticResource BlinkingStyle}")
あとは、Style を適用した Textblock の IsEnabled を操作すると、点灯と点滅が切り替わります。
いや、IsEnabled に紐づけるのどうなん?という人は DataTrigger あたりを検討してみてください。
あるいは Style を適用せず直接コードビハインドで操作したい、という場合は以下のコードを適用します。
Private _text1Blinking As Storyboard
Private Sub StartBlinkingClick(sender As Object, e As RoutedEventArgs)
' Stackpanel.Resources を記述している StackPanel に x:Name="rootPanel" を追記してから以下を実行
_text1Blinking = CType(Me.rootPanel.Resources("BlinkingStoryboard"), Storyboard)
_text1Blinking.Begin(Me.Text1, True)
End Sub
Private Sub StopBlinkingClick(sender As Object, e As RoutedEventArgs)
_text1Blinking.Stop(Me.Text1)
End Sub
posted in Program , VB.NET , WPF , xaml by ooltcloud | No Comments
2017年3月2日
posted in ハードウェア by ooltcloud | 10 Comments
2016年8月19日
諸般の事情 (Expressweb のサービス停止 ) により、こちらに移転しました。
移転元サイト (http://ooltcloud.expressweb.jp/ ) は、Expressweb のサービス停止と同時に消滅、リンク切れする予定です。(2016 年 9 月末までは存在する予定です)
posted in 移転 by ooltcloud | No Comments
2016年7月15日
VHS デッキの国内製造が終了との由…
船井電機、VHSデッキ撤退へ…国内で唯一生産
船井電機は、VHS方式の家庭用ビデオデッキの生産を7月末で終了する。
http://www.yomiuri.co.jp/economy/20160714-OYT1T50096.html
過去のメディアがどんどん読めなくなっていくというのは寂しいね。
posted in 時事 by ooltcloud | No Comments
2016年6月14日
ある日、マシン A で作成した Visual Studio 2012 の WPF のプロジェクトを、別のマシン B で開き、WPF デザイナを表示しようとしたら、「Microsoft Silverlight SDK 5.0 は見つかりませんでした」なるエラーが表示され、画面をみることができないという自体に出くわした・・・(汗
マシン A では問題なく画面は表示されるのに・・・。もちろん マシン A, B ともに Visual Studio のバージョンは同一です。
「デザイナーを再度読み込」んでみてもダメ。ただ、この状態でもビルドは通る。純粋にデザイナーの表示がダメなだけ。
エラーの詳細をみても確かに Silverlight に関わるエラーであることには間違いない。でもこのプロジェクト、Silverlight ではなく WPF なんですけど・・・
ひらく とじる
System.NotSupportedException
Microsoft Silverlight SDK 5.0 は見つかりませんでした。正しいバージョンの Microsoft Silverlight SDK がインストールされていることを確認してください。
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.WaitForCompletion(NestedCallContext nestedCallContext, BlockingCall call, WaitHandle timeoutSignal)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.MarshalOutSynchronous(Action action, Int32 targetApartmentId, WaitHandle aborted, WaitHandle timeoutSignal)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.MarshalOut(Action action, Int32 targetApartmentId, WaitHandle aborted, CallSynchronizationMode syncMode, WaitHandle timeoutSignal)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.MarshalOut[TValue](RemoteHandle`1 targetObject, Action action, CallSynchronizationMode syncMode)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.MarshalOut[TResult,TValue](RemoteHandle`1 targetObject, Func`2 func, CallSynchronizationMode syncMode)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.LocalDesignerService.CreateDesignerImpl(IHostSourceItem item, IHostTextEditor editor, RemoteCancellationToken remoteCancelToken)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.LocalDesignerService.<>c__DisplayClass12.b__11(RemoteCancellationToken remoteToken)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.LocalDesignerService.CallWithCancellation[TResult](CancellationToken cancelToken, Func`2 func)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.LocalDesignerService.Microsoft.Expression.DesignHost.IDesignerService.CreateDesigner(IHostSourceItem item, IHostTextEditor editor, CancellationToken cancelToken)
場所 Microsoft.Expression.DesignHost.IsolatedDesignerService.IsolatedDesignerView.CreateDesignerViewInfo(CancellationToken cancelToken)
System.NotSupportedException
Microsoft Silverlight SDK 5.0 は見つかりませんでした。正しいバージョンの Microsoft Silverlight SDK がインストールされていることを確認してください。
Server stack trace:
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.WaitForCompletion(NestedCallContext nestedCallContext, BlockingCall call, WaitHandle timeoutSignal)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.MarshalIn(Action action, Int32 targetApartmentId)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.MarshalIn(IRemoteObject targetObject, Action action)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.MarshalIn[TResult](IRemoteObject targetObject, Func`1 func)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteDesignerService.Microsoft.Expression.DesignHost.Isolation.Remoting.IRemoteDesignerService.CreateDesigner(IRemoteHostSourceItem remoteItem, IRemoteHostTextEditor remoteEditor, IRemoteCancellationToken remoteToken)
場所 System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
場所 System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)
Exception rethrown at [0]:
場所 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
場所 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.IRemoteDesignerService.CreateDesigner(IRemoteHostSourceItem remoteItem, IRemoteHostTextEditor remoteEditor, IRemoteCancellationToken cancelToken)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.LocalDesignerService.<>c__DisplayClass8.b__6(IRemoteDesignerService d)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.<>c__DisplayClass4`2.b__3()
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.Call.InvokeWorker()
System.NotSupportedException
Microsoft Silverlight SDK 5.0 は見つかりませんでした。正しいバージョンの Microsoft Silverlight SDK がインストールされていることを確認してください。
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.WaitForCompletion(NestedCallContext nestedCallContext, BlockingCall call, WaitHandle timeoutSignal)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.MarshalOutSynchronous(Action action, Int32 targetApartmentId, WaitHandle aborted, WaitHandle timeoutSignal)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.MarshalOut(Action action, Int32 targetApartmentId, WaitHandle aborted, CallSynchronizationMode syncMode, WaitHandle timeoutSignal)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.MarshalOut[TValue](RemoteHandle`1 targetObject, Action action, CallSynchronizationMode syncMode)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.MarshalOut[TResult,TValue](RemoteHandle`1 targetObject, Func`1 func, CallSynchronizationMode syncMode)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteWrapper`1.Invoke[T](Func`2 action)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteHostPlatformService.Microsoft.Expression.DesignHost.IHostPlatformService.GetProperty(String frameworkSpec, String propertyName)
場所 Microsoft.Expression.DesignSurface.PlatformContext.GetProperty(String frameworkSpec, String propertyName)
場所 Microsoft.Expression.Platform.PlatformService.GetProperty(String frameworkSpec, String propertyName)
場所 Microsoft.Expression.DesignSurface.Assemblies.SilverlightAssemblyResolver.GetSilverlightPlatformPaths(String assemblyName)
場所 Microsoft.Expression.DesignSurface.Assemblies.SilverlightAssemblyResolver.LoadSilverlightPlatformAssembly(String assemblyName)
場所 Microsoft.Expression.DesignSurface.Assemblies.SilverlightAssemblyResolver.ResolveRuntimeAssembly(AssemblyName assemblyName)
場所 Microsoft.Expression.Platform.PlatformService.ResolvePlatformAssembly(AssemblyName assemblyName)
場所 Microsoft.Expression.DesignSurface.DesignerContext.PlatformAssemblyResolver.ResolveAssembly(AssemblyName assemblyName)
場所 Microsoft.Expression.DesignSurface.Assemblies.AssemblyService.ResolveAssembly(AssemblyName assemblyName, IEnumerable`1 assemblyResolverTable)
場所 Microsoft.Expression.DesignSurface.Assemblies.AssemblyService.ResolveAssembly(String assemblyPath, String assemblyFullName, String projectPath, IHostShadowCopyTask hostShadowCopyTask)
場所 Microsoft.Expression.DesignSurface.Assemblies.ProjectAssemblyResolver.GetAssemblyInformation(String path, String assemblyFullName)
場所 Microsoft.Expression.DesignSurface.Assemblies.ProjectAssemblyResolver.GetAssemblyInformation(IHostReferenceItem reference)
場所 Microsoft.Expression.DesignSurface.Assemblies.ProjectAssemblyResolver.UpdateAssemblyReferences(IEnumerable`1 referencesToUpdate)
場所 Microsoft.Expression.DesignSurface.Assemblies.ProjectAssemblyResolver..ctor(IHostProject project, DesignerContext designerContext)
場所 Microsoft.Expression.DesignSurface.Assemblies.ProjectAssemblyService.<.ctor>b__0(IHostProject project)
場所 Microsoft.Expression.Utility.Collections.SuspendableKeyedCollection`2.CreateItems(TKey key)
場所 System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
場所 Microsoft.Expression.Utility.Collections.SuspendableKeyedCollection`2.GetItem(TKey key)
場所 Microsoft.Expression.DesignSurface.Assemblies.ProjectAssemblyService.GetProjectAssemblyResolver(IHostProject project)
場所 Microsoft.Expression.DesignSurface.Project.ProjectContextBase.Initialize()
場所 Microsoft.Expression.DesignSurface.Project.XamlProjectContext.Initialize()
場所 Microsoft.Expression.DesignSurface.Project.ProjectContextManager.GetProjectContext(IHostProject project, IPlatform platform, Boolean create)
場所 Microsoft.Expression.DesignSurface.Project.ProjectContextManager.d__d.MoveNext()
場所 Microsoft.Expression.DesignSurface.Project.ProjectContextBase.XamlProjectMetadata.GetAssemblyForTypeResolve(String assemblyName)
場所 Microsoft.Expression.DesignModel.Metadata.TypeResolver.GetType(ClrNamespaceIdentifier clrNamespaceIdentifier, String typeName)
場所 Microsoft.Expression.DesignModel.Metadata.TypeResolver.ResolveType(ITypeId typeId)
場所 Microsoft.Expression.DesignModel.Metadata.ProjectNeutralTypesAttributeTable.ResolveType(ITypeResolver typeResolver, ITypeId typeId)
場所 Microsoft.Expression.DesignModel.Metadata.ProjectNeutralTypesAttributeTable.RegisterDataGridAttributeTable(ITypeResolver typeResolver)
場所 Microsoft.Expression.WpfPlatform.WpfPlatform.RefreshProjectSpecificMetadata(ITypeResolver typeResolver, ITypeMetadataFactory typeMetadataFactory)
場所 Microsoft.Expression.DesignSurface.Project.ProjectContextBase.Initialize()
場所 Microsoft.Expression.DesignSurface.Project.XamlProjectContext.Initialize()
場所 Microsoft.Expression.DesignSurface.Project.ProjectContextManager.GetProjectContext(IHostProject project, IPlatform platform, Boolean create)
場所 Microsoft.Expression.DesignSurface.Project.ProjectContextManager.GetSourceItemContext(IHostSourceItem sourceItem)
場所 Microsoft.Expression.DesignSurface.DesignerService.CreateDesigner(IHostSourceItem item, IHostTextEditor editor, CancellationToken cancelToken)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteDesignerService.<>c__DisplayClass10.<>c__DisplayClass12.b__f(CancellationToken cancelToken)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteDesignerService.CallWithCancellation[TResult](IRemoteCancellationToken remoteToken, Func`2 func)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteDesignerService.<>c__DisplayClass10.b__e()
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.<>c__DisplayClass16`1.b__15()
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.Call.InvokeWorker()
System.NotSupportedException
Microsoft Silverlight SDK 5.0 は見つかりませんでした。正しいバージョンの Microsoft Silverlight SDK がインストールされていることを確認してください。
Server stack trace:
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.WaitForCompletion(NestedCallContext nestedCallContext, BlockingCall call, WaitHandle timeoutSignal)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.MarshalIn(Action action, Int32 targetApartmentId)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.MarshalIn(IRemoteObject targetObject, Action action)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.MarshalIn[TResult](IRemoteObject targetObject, Func`1 func)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteWrapper`1.Invoke[T](Func`2 action)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteHostPlatformService.Microsoft.Expression.DesignHost.IHostPlatformService.GetProperty(String frameworkSpec, String propertyName)
場所 System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
場所 System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)
Exception rethrown at [0]:
場所 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
場所 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
場所 Microsoft.Expression.DesignHost.IHostPlatformService.GetProperty(String frameworkSpec, String propertyName)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteHostPlatformService.<>c__DisplayClass1.b__0(IHostPlatformService s)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteWrapper`1.<>c__DisplayClass4`1.b__3()
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.<>c__DisplayClass7`2.b__6()
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.Call.InvokeWorker()
System.NotSupportedException
Microsoft Silverlight SDK 5.0 は見つかりませんでした。正しいバージョンの Microsoft Silverlight SDK がインストールされていることを確認してください。
場所 Microsoft.Expression.HostUtility.Platform.SilverlightDomainFactory.get_ReferenceAssembliesPath()
場所 Microsoft.Expression.HostUtility.Platform.HostPlatformService.GetProperty(String frameworkSpec, String propertyName)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteHostPlatformService.<>c__DisplayClass1.b__0(IHostPlatformService s)
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.RemoteWrapper`1.<>c__DisplayClass4`1.b__3()
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.ThreadMarshaler.<>c__DisplayClass16`1.b__15()
場所 Microsoft.Expression.DesignHost.Isolation.Remoting.STAMarshaler.Call.InvokeWorker()
そういえばこのプロジェクト。PCL (Portable Class Library) を参照していたのでした。でも、Silverlight 5 ではなく、Silverloight 4 を要件に設定しています。
SDK がないというので、とりあえずインストール状況を確認してみます。すると。
マシン A のインストール状況。SDK がある。
マシン B のインストール状況。SDK がない・・・(汗
原因はこれですか。同じようにインストールしていたはずなのに。だれだ、マシン B から SDK Uninstall したのは・・・
いやいや、そもそも PCL を採用したのは、このライブラリはプラットフォーム依存を排除したかったからで。なのに SDK がないとデザイナーが開けなくなるとかアリ? _| ̄|○
そして、PCL を普通のライブラリ(DLL)に作り直して参照設定し直したら、無事デザイナーは例外を吐かなくなりました・・・(汗
ちなみに、設定を変えることで「PCL から普通の DLL にする」といったことは出来ませんでした。(できるのかもしれないけどやり方が分からなかった)
教訓。ランタイムはポータブルでも開発環境はポータブルではない場合がある(追加のSDKをインストールする必要がある)点に注意(大汗
posted in WPF by ooltcloud | No Comments
2016年6月13日
Excel 2010 で貼り付けた画像を切り取りや削除を行った場合に、画像が残ってしまうことがあります。スクロールさせて再描画すると消えるので、オブジェクトそのものは消えているのにもかかわらず!(汗
ぐぐると、改ページプレビューがよくないとか、ハードウェアグラフィックアクセラレーターの設定を無効にすればいいとか、KB をあてたらいいとか色々あるのですが。
もしかしたら、そんなことではなく、印刷設定の変更で対応できるかもしれません。
まず、削除しても画像が残るシートの「印刷範囲」は A:M のように、列指定になっているかを確認します。
その「印刷範囲」を 行方向無限の設定をやめて、A1:M42 のように行方向の範囲を決めてやれば、削除しても画像が残らなくなります。(多分)
特定のシートだけ削除した画像が残る、とか、新しく作った Workbook では再現しない、とかだと印刷範囲を疑ってみると解決するかもしれません。
・・・もっとも根本的な解決方法ではないので、対応する KB があるのであれば (= あるのかどうかは知らない) それを充てるのが良いです。ですが、勝手に KB を当てるわけにはいかない環境もあるので、そういう場合は上記を試してみるのもよいと思います。
posted in Excel , Office by ooltcloud | 1 Comment
2016年4月10日
一年に一回程度しか成端工作をしない人向け…というか自分向けにメモ。
なぜならば、一つ成端するのに1時間の時間と2つのコネクタを無駄にしたので(汗
まず外被(シース)を剥きます。
このとき 10cm くらい剥いてしまいます。勿体ない気がしますが、これは後の工程でヨリを戻しやすくするためと芯線の配列を揃えやすくするためです。最初から必要最小限の長さ(1.2cm 程度)にしてしまうと作業がまるで進まなくなったりします。
また、外被を剥くのにカッターナイフを使用します。下手にストリッパーを使うと芯線側の絶縁被覆を傷つけることがあるので、数本の加工なら使わないほうが良いと思います。
次にヨリをほどきます。
ヨリは根元側から先端側に向けてほどくと、根元側のヨリがよりほどけるので、後で作業がしやすいです。
T568A または T568B のいずれかの並びに揃えます。
このときの注意点としては、外被から 5mm 程度先の根元で揃っているようにします。
先端は後で切り落としてしまうので、先端側で揃えても意味がないことに注意します。
(下の写真は T568B 配列)
T568A の配列
T568B の配列
芯線を外被の先端から 1.2cm 程度のところで切り落とします。
コネクタに挿します。
このとき、並びが正しいかを確認するとともに、単色とストライプが交互になっているかを確認します。
特に片側の端が単色ならもう片側の端はストライプであることを確認します。単色同士だったりストライプ同士だったりすると間違っているので直します。
配列が正しければ押し込みます。
押し込んでコネクタの先端まで芯線が差し込まれていることを確認します。
(下の写真は数本差し込み不足があります)
横からみても奥まで差し込まれているかを確認します。
(下の写真は差し込み不足です)
奥まで差し込んだら圧着工具で圧着します。
芯線を押し込む力を弱めると、上の写真のように芯線の差し込みが緩んでしまうので、芯線は押し付けたまま圧着します。
圧着が終了したらケーブルテスターで結線をチェックして、問題なければ終了です。
posted in ネットワーク , ハードウェア by ooltcloud | No Comments
2016年2月22日
浮動小数点型と整数型で、互いに誤差なく交換できる最大の整数がいくらなのかを確認。
結論は以下。
・倍精度浮動小数点の場合は ±9007199254740992 (2^53)
・倍精度浮動小数点の場合は ±16777216 (2^24)
これは IEEE754 の仮数部の桁数から導くことができます。
ただ、.net 系で浮動小数点数を書式整形して表示するとおかしなことになる場合があります。
Dim a As Double = 2 ^ 53
Dim b As Double = a - 1
Dim c As Long = b
Console.WriteLine("{0:################}", b)
Console.WriteLine("{0:################}", c)
結果
9007199254740990
9007199254740991
続行するには何かキーを押してください . . .
b を c に代入すると正しく 9007199254740991 と表示されるのに、b を直接表示すると 9007199254740990 になってしまいます。
上記は倍精度実数の場合ですが、単精度実数の場合でも同様の現象が起こります。
Dim a As Single = 2 ^ 24
Dim b As Single = a - 1
Dim c As Long = b
Console.WriteLine("{0:########}", b)
Console.WriteLine("{0:########}", c)
16777220
16777215
続行するには何かキーを押してください . . .
10 進数換算で、倍精度の場合 15.6 桁、単精度で 6.9 桁が有効桁数です。従って、10 進数でその桁の数値を全桁を正確に表すことができない桁(倍精度の場合 16 桁目, 単精度の場合 7 桁目) に至る場合は、なんらかの指数計算が行われてしまう、ということのようです。(多分)
まあ正しく表示しろ、って言われると 0.1 は 0.1000000000000000055511151228 になっちゃいますしね。ここは精度範囲外ってことで諦めですね。
したがって、浮動小数点で整数を表現する場合、倍精度の場合 ±9007199254740992 (2^53), 単精度の場合は ±16777216 (2^24)。しかし、10進数表示を考慮に入れるなら、倍精度は 15 桁、単精度は 6 桁以内ということです。
余談ですが javascript だと Number.MAX_SAFE_INTEGER で +9007199254740992 が得られるようです。(.net 系でもこのプロパティ欲しい)
posted in Java Script , Program , VB.NET by ooltcloud | No Comments
2016年2月22日
たとえば、以下のようなプログラムを実行します。
Sub Main()
Dim sw = New Stopwatch
sw.Start()
For i = 1 To 1000
' 1ms 待ち
Threading.Thread.Sleep(1)
Next
sw.Stop()
Console.WriteLine("経過 {0} ms", sw.Elapsed.TotalMilliseconds)
End Sub
1ms 待ちを 1000 回繰り返しているだけなので、期待値は 1秒(1000ms) ですがそうはなりません。
実際に実行すると、以下のように 15 秒前後かかります。
C> ConsoleApplication1
経過 15076.4839 ms
これは、システムクロックの精度がデフォルトでは 15.625 ms であるためです。
つまり、1ms 止めているつもりが、システムクロックの精度が 15.625 ms であるため、15ms 前後止まっているということです。
現在のシステムクロックの精度は Sysinternal ツールの Clockres を使うことで確認できます
https://technet.microsoft.com/ja-jp/sysinternals/bb897568.aspx
C>clockres
ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com
Maximum timer interval: 15.625 ms
Minimum timer interval: 0.500 ms
Current timer interval: 15.625 ms
ということで、このシステムクロックの精度を15.625 ms から 1ms に変えてやれば、冒頭のプログラムは期待通りに動いてくれそうです。
ということで、以下のプログラムによって、システムクロックの精度を 1ms に変えます。
Private Declare Sub NtSetTimerResolution Lib "ntdll.dll" Alias "NtSetTimerResolution" _
(
ByVal desiredResolution As UInt32,
ByVal setResolution As Boolean,
ByRef CurrentResolution As UInt32
)
Sub Main()
' 1ms : 100ns (NtSetTimerResolution の設定の分解能が 100ns であるため)
Const RATIO = 10 * 1000
' 変更値 (1ms)
Dim modifyMilliseconds As Double = 1
' 変更
Dim currentMilliseconds = 0
NtSetTimerResolution(CInt(modifyMilliseconds * RATIO), True, currentMilliseconds)
' 結果
Console.WriteLine("Current timer interval: {0}ms", currentMilliseconds / RATIO)
Console.Read()
End Sub
プログラムが終了してしまうとデフォルト値に戻ってしまうので、何かキーを入力しないと、プログラムの終了をしないようにしています。
上記のプログラムを実行中に、冒頭のプログラムを実行してみます。
その結果は以下。
C> clockres
ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com
Maximum timer interval: 15.625 ms
Minimum timer interval: 0.500 ms
Current timer interval: 1.000 ms
C> ConsoleApplication1
経過 1718.0604 ms
結果は約 1.7 秒と、まだ理論値からは外れているものの、デフォルトのシステムクロック精度のときの約 15 秒よりも大幅に理論値に近くなりました。
このように、ms 単位の待ち時間やタイマー割り込みを使用する場合は、システムクロックの精度を気にする必要があります。
加えて、システムクロックの精度の変更は、そのアプリケーションだけでなく Windows 全体に影響が及ぶので、軽率に変更するべきではない点にも注意が必要です。
posted in OS , Program , VB.NET , Windows by ooltcloud | No Comments
2016年1月7日
Oracle で浮動小数点数を扱いたい場合、BINARY_FLOAT という型があるようです。
create table test (
a BINARY_FLOAT
);
無限大、非数も定義できるようです。
insert into test values (1000000.0);
insert into test values (0.0000001);
insert into test values (BINARY_FLOAT_INFINITY);
insert into test values (-BINARY_FLOAT_INFINITY);
insert into test values (BINARY_FLOAT_NAN);
select の結果は以下。
SQL> select * from test;
A
----------
1.0E+006
1.0E-007
Inf
-Inf
Nan
posted in Oracle , データベース by ooltcloud | No Comments
2015年12月30日
posted in Program , VHDL by ooltcloud | No Comments
2015年12月30日
Oracle で password という文字列を、秘密鍵 'key12345' で DES で暗号化してみます。
SQL> select
2 rawtohex(
3 dbms_obfuscation_toolkit.desencrypt(
4 input_string => 'password',
5 key_string => 'key12345'
6 )
7 ) as Encrypted
8 from dual;
ENCRYPTED
-----------------------------------------------------
3437EBBCAD1BB618
dbms_obfuscation_toolkit.desencrypt で暗号化するわけですが、戻ってくるものは文字列ではないので、rawtohex で16進数表示化をしています。
この結果を Powershell で正しいかどうかを検証します。
暗号化を行うコマンドレットは標準では用意されていないようなので、まずは以下のような関数を作成します。
要するに .net のクラスライブラリの力を借ります。
function Encrypt($inputString, $keyString) {
# 暗号化プロバイダの生成とモードの設定
$des = New-Object System.Security.Cryptography.DESCryptoServiceProvider
$des.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
# 秘密鍵と初期化ベクタ(IV)の設定
$des.Key = [System.Text.Encoding]::ASCII.GetBytes($keyString)
$des.IV = [Byte[]](0,0,0,0,0,0,0,0)
# 暗号化対象の設定
$inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputString)
$params = ($inputBytes, 0, $inputBytes.Length)
# 暗号化
$encrypter = $des.CreateEncryptor()
$encBytes = [System.Security.Cryptography.ICryptoTransform].GetMethod("TransformFinalBlock").Invoke($encrypter , $params)
$encrypter.Dispose()
#リターン
Write-Output $encBytes
}
# パラメータ
$inputString = "password"
$keyString = "key12345" # 8byte以上が必要
# 暗号化
$encBytes = Encrypt $inputString $keyString
[System.BitConverter]::ToString($encBytes)
実行結果
34-37-EB-BC-AD-1B-B6-18
ついでに、この暗号が復号できるかを確認してみます。
function Decrypt($inputBytes, $keyString) { #(★)
# 暗号化プロバイダの生成とモードの設定
$des = New-Object System.Security.Cryptography.DESCryptoServiceProvider
$des.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
# 秘密鍵と初期化ベクタ(IV)の設定
$des.Key = [System.Text.Encoding]::ASCII.GetBytes($keyString)
$des.IV = [Byte[]](0,0,0,0,0,0,0,0)
# 暗号化対象の設定
$params = ($inputBytes, 0, $inputBytes.Length)
# 復号化(★)
$decrypter = $des.CreateDecryptor()
$decBytes = [System.Security.Cryptography.ICryptoTransform].GetMethod("TransformFinalBlock").Invoke($decrypter , $params)
$decrypter.Dispose()
#リターン(★)
$decString = [System.Text.Encoding]::ASCII.GetString($decBytes)
Write-Output $decString
}
# パラメータ
$inputBytes = [Byte[]](0x34, 0x37, 0xEB, 0xBC, 0xAD, 0x1B, 0xB6, 0x18)
$keyString = "key12345" # 8byte以上が必要
# 復号化
Decrypt $inputBytes $keyString
結果
password
posted in Oracle , PowerShell , Program , データベース by ooltcloud | No Comments
2015年12月12日
なんか、カープとメガフォンと私 Advent Calendar 2015 に召喚されてしまったので、書いてみる。
広島って優勝しないですよね。しかも今年など、最後の最後で負けて B クラス落ちとは何事!という感じ(汗
そういえば、広島ってここぞという勝負にめっぽう弱い印象。個人的に記憶に残っている「ここぞというところで負ける」といえば、新市民球場初戦敗退、旧市民球場最終戦敗退、1986年の日本シリーズ1分け3連勝からの4連敗、が思い起こされる(汗
ただやっぱりそれより強烈な印象があるのは、1979年 V2 のときか、その翌年の V3 のときに、マジックが30くらいで点灯してから、そのままマジックが減っていって優勝したときのこと。当時、紙屋町そごうの垂れ幕でマジックのカウントダウンをやっていて。紙屋町のバス停で帰りのバスを待ちながら、その数字が減っていくのを眺めていたんですよね。是非あれをもう一度みたい!
そういうわけなので、来年こそ、なんとか優勝してほしいのです。
posted in 与太話 by ooltcloud | No Comments
2015年12月3日
この記事は、ふつうの広島 Advent Calendar 2015 3日目の記事です。
今年も 12月3日 を迎えることができました。昨日は 12月2日 でしたから当然です? そう考えるのがふつーですよね。
ところが、12月2日 の翌日が 12月3日 でなかった年がむかしあったのです。
それは 明治5年。この年の12月2日の翌日は 明治6年1月1日 となりました。なぜかというと、それまでの旧暦(太陰太陽暦)から現在の太陽暦(グレゴリオ暦) に改暦したからです。
つまり・・・
12月の工数は2日間だけってことですね。一気に一か月納期が短縮したようなものです。
さらにこの改暦の布告は、改暦の約一か月前の 11月9日 です。年明けリリース!なんてスケジュールだったりすると、残り2ヵ月あったはずが一瞬にして残り1ヵ月です。プロマネもびっくりです。でも決まったことをとやかく言っても仕方ありません。やるしかないです。プロマネはプログラマー叱咤 激励 し、プログラマーは昼夜の別なく作業して、納期に間に合わせなくてはなりません。レッツデスマーチですね!
ふつーに 12月2日 の翌日に 12月3日 が来るって大切!
今年もちゃんと 12月3日が来てよかった。
ところでその時の給料ですが。当時は月給制でした。なので、2日でも1ヵ月ですから1ヵ月分の給料が!とおもいきや、2日しかないんだから12月の給料はナシね、という話になます。加えて、翌明治6年は旧暦のままであれば閏月のある年なので13ヵ月分の給料が貰える年だったのですが、太陽暦に変わったことでそれもなくなり・・・ もちろん月あたりの日数も約1日増えたわけでして(汗
しかし、まあ改暦自体「給料を払いたくない」というのが動機らしいという話もあり、昔も今もあまり変わらず、ふつーに ブラック 厳しかったんですねえ、ということで。(残業代なんて制度もなかったでしょうしね)
参考
明治5年
https://ja.wikipedia.org/wiki/明治5年
月給制
https://kotobank.jp/word/月給制
posted in 与太話 by ooltcloud | No Comments
2015年11月4日
たとえばこんなバッチファイル (a.bat) があるとして。
SET AAA=ABC123
echo 設定しました。
Powershell でこのバッチファイルを呼び出し、このバッチファイルで設定されている環境変数の値を Powershell 側で取得したい場合、以下のように書くことで取得できます。
PS> $a = cmd /c "@echo off & call a.bat > nul & call echo %AAA%"
PS> $a
ABC123
ポイントは、環境変数を Powershell で取得するに際し標準入出力を使っていることと、環境変数の値を標準出力に出力するに際して、call echo ~、と call をつかっているところでしょうか。
この方法では別の問題が発生する場合もありますが、まあ一つの方法としてメモ。
posted in OS , PowerShell , Windows by ooltcloud | No Comments