2017年11月23日木曜日
Oracle Data Provider for .NET (ODP.NET) で ORA-12154 が発生した場合の対処
11月 23, 2017

オフィス狛 技術部です。
弊社では、C# を使ってOracleに接続する際は、
Oracle Data Provider for .NET (ODP.NET) を使用する機会が多いです。
Oracle Clientのインストールが不要で、Oracleに接続出来るのが、やっぱり強みですね。
ただ、Oracle Clientと全く関係ないかと言うと、そうでもないので、トラブルが発生する事があります。
今回、とあるWebサーバーのOracleへの接続設定を変更した際、以下のようなエラーが発生しました。
ORA-12154:TNS: 指定された接続識別子を解決できませんでした
接続情報はプログラム側とWeb.config側で、以下のように設定しています。
[プログラム側]
private OracleConnection _con;
private string _constr = "User Id=komauser;"
+ "Password=komapass;"
+ "Data Source=SRC_TEST";
public void Connect()
{
try
{
this._con = new OracleConnection(this._constr);
this._con.Open();
}
catch (Exception ex)
{
throw ex;
}
}
[Web.config側]
<configuration>
--(中略)--
<oracle.manageddataaccess.client>
<version number="*">
<dataSources>
<dataSource alias="SRC_DEV" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.1.111)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=komadb))) " />
</dataSources>
</version>
</oracle.manageddataaccess.client>
</configuration>
「Data Sourceの指定が間違えている」とすぐ気付くかもしません。
ただ、今回はそれに気付かず、数時間悩んでしまいました。
気付かなかった理由として、
今回、変更したのは接続先のIPアドレスだけで、変更前は確かに接続出来ていたからです。
そうなると、もうネットワークとかその辺の設定ミスを疑ってしまいます。
まあ、結局数時間後に気付いたのですが、
では何故変更前はこの状態で接続出来たのか・・・。
実は、ODP.NET(パッケージはOracle.ManagedDataAccess.Client ) が Data Source を判断するのは、優先順位があります。
Oracle Data Provider for .NET, Managed Driver Configuration dataSources Section
によると、最優先は「 Web.config の oracle.manageddataaccess.client タグ」なのですが、
そこに合致しない場合は、「tnsnames.ora」を参照するようです。
と言う訳で、該当のWebサーバーを調べたら・・・「tnsnames.ora」ありました。
そこにしっかりと、
SRC_TEST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.110)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = komadb)
)
)
と記載されていました。と言う訳で、
ODP.NET で 接続がうまくいかない場合、Data Source の指定を疑ってみましょう、と言う話でした。
2017年5月27日土曜日
AWS EC2 で Amazon Linux を使用する場合に最初にやること
5月 27, 2017

初稿:2017年5月27日
修正:2018年9月16日 Amazon Linux 2 から、cloud-initが無くなった事による修正。
オフィス狛 技術部です。
AWSでEC2インスタンスを立ち上げる度に、設定すべき事を忘れてしまうので、
備忘録の為にブログに残しておこうと思います。
「aws ec2 やる事」でググると、もっと細くやる事を記載している方も居るので、
しっかりやりたい方は、それらを参考にして下さい。
ここに記載するのは、本当に最低限の設定です。
何はともあれ yum update
まずは yum update です。$ sudo yum update -y
タイムゾーンの変更
Amazon Linux はデフォルトのタイムスタンプが UTC になっているので、日本時間に変更します。$ date 2017年 5月 20日 土曜日 02:33:43 UTC $ sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime $ date 2017年 5月 20日 土曜日 11:35:33 JST
このままでは、サーバーの再起動を行うと UTC に戻ってしまうので、設定を変更します。
$ sudo vim /etc/sysconfig/clock
※「ZONE="UTC"」となっている部分を「ZONE="Asia/Tokyo"」に変更します。
ec2-user の 削除
ec2-user はデフォルトのユーザーなので、セキュリティ上、削除しておいた方が良いです。(もちろん変わりのユーザーも作成します。)
まずは、新規ユーザー(ofkomauser)を追加します。
$ sudo useradd ofkomauser
鍵などをec2-userからコピーし、権限設定を行います。
$ sudo cp -arp /home/ec2-user/.ssh /home/ofkomauser/ $ sudo chown -R ofkomauser /home/ofkomauser/.ssh
新しいユーザーのパスワードを設定します
$ sudo passwd ofkomauser
sudoersファイルを編集し、新しいユーザーで sudo が使えるようにします。
修正:Amazon Linux 2 から、cloud-initが無くなり、90-cloud-init-usersを編集する事になっています。
$ sudo visudo -f /etc/sudoers.d/cloud-init
$ sudo visudo -f /etc/sudoers.d/90-cloud-init-users
※「ec2-user」の部分をコメント化、もしくは削除し、新しいユーザーを追加します。
# User rules for ec2-user #ec2-user ALL=(ALL) NOPASSWD:ALL ofkomauser ALL=(ALL) NOPASSWD:ALL
そして、最後に「ec2-user」を削除します。
$ sudo userdel -r ec2-user
以上が、最低限の設定になります。
EC2の用途によっては、もっと細かい設定は必要ですが、
それはまった追って記事にしようと思います。
2017年5月6日土曜日
Codeigniter で他システムとセッション共有する場合に、$_SESSION が消えてしまう
5月 06, 2017
オフィス狛 技術部です。同じドメイン配下に存在する別システム(Codeigniter ではないPHPを使ったシステム)と、
セッションを共有する・・・つまり、$_SESSION で値をやりとりする事になったのですが、
Codeigniter 側で $_SESSION から値を取ろうとすると、空になっている現象が発生しました。
単純には行かないのですね、やっぱり。
※ちなみに、Codeigniter のバージョンは 3.1.2 です。
1)セッションIDを調べてみる
セッションIDが変わってしまって、違うセッションを見ているのかと思い、$_COOKIE を調べたところ、session_id は同じでした。
(同じドメインですし、敢えてセッションを変えるような設定もしていないので)
セッションIDが同じで値が取れないのであれば、どこかで値を消している、という事になります。
2)Codeigniter を使用していないPHPシステムで試してみる
Codeigniter を使用していない、Webサーバー上に置いただけのPHPファイルで試してみたところ、$_SESSION から値が取れる事が確認出来ました。
という事は、Codeigniter でセッションを消している事になります。
3)Codeigniter の Session.php を調べてみる
というわけで、Codeigniter の System/libraries/Session に存在する、「Session.php」を調べてみました。
105行目付近に、
$class = $this->_ci_load_classes($this->_driver);という記述があり、このタイミングで driver を変更しているため、
この処理以降に設定した driver のセッションを参照しているのではないかと予想できます。
※実際、この処理の直前では $_SESSION の値は取得できたが、
直後には値が消えていた事を確認しています。
4)対応方法(暫定)
とりあえず、先程の記述の直前で、// 追加ここから session_start(); $session = $_SESSION // 値を一時変数に格納 session_write_close(); // 追加ここまで $class = $this->_ci_load_classes($this->_driver);と記載します。実は、session_start 自体はもっと後で行うのですが、
ここで一旦スタートさせて、$_SESSION の値を退避しておきます。
(closeも忘れずに)
そして、今度は、元々あった「session_start」(150行目近辺)の後に、
session_start(); //追加ここから $_SESSION = $session; // 値を一時変数から再設定 // 追加ここまでと追加する事で、他システムで設定された $_SESSION を利用する事ができます。
5)本当はどう対応するべきなのか
実は、弊社側のシステムは、セッションをDBに保存する設定にしています。そしておそらく、他システム側は、セッションはファイル保存していると思います。
(弊社保有のシステムでは無いので、実際は分からないですが・・・)
ですので、$_SESSION が消えてしまうのも、当然と言えば当然なのです。
だとするならば、
こちら側の driver を「files」にして、保存パスを共有した場合、うまくいきそうな気がします。
※ちなみに、設定出来る driver は、本家サイト(翻訳版)に記載してありますが、
- files(デフォルト; ファイルシステムベース)
- database
- redis
- memcached
今回は、テスト環境含め、弊社が触れる環境では無いので、
色々試せないですが、いずれ社内に環境作って試してみようと思います。
2017年4月21日金曜日
Jenkins をアップデートしたら、 HTTP ERROR 503 Service Unavailable が発生
4月 21, 2017
オフィス狛 技術部です。Jenkinsは、頻繁にアップデートが出るので、本番稼働中だったりするとなかなか反映できません。
今回も、以下のようなアラートが出たので、まずは開発環境からアップデートする事に。
弊社の場合、JenkinsをインストールしているのはAWS EC2なので、一番簡単なアップデートは、
sudo yum update です。
そして、アップデートした後に、接続してみると・・・
「HTTP ERROR 503 Service Unavailable」になりました。
・・・・だから、嫌なんですよ、この類のアップデート。と愚痴っても仕方ないです。
いきなり本番環境をアップデートしなかった事をラッキーと思わないと。
(いや、しないですけどね、そんな事)
ログを確認すると、以下の内容でした。
「UnsupportedClassVersionError」?
何かが古い?
WARNING: Failed startup of context w.@a38dddf{/,file:/var/cache/jenkins/war/,STARTING}{/var/cache/jenkins/war}
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.eclipse.jetty.webapp.IterativeDescriptorProcessor.visit(IterativeDescriptorProcessor.java:85)
(中略)
at Main._main(Main.java:264)
at Main.main(Main.java:112)
Caused by: java.lang.UnsupportedClassVersionError: jenkins/util/SystemProperties : Unsupported major.minor version 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:803)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
(中略)
at org.eclipse.jetty.server.handler.ContextHandler.loadClass(ContextHandler.java:1583)
at org.eclipse.jetty.webapp.StandardDescriptorProcessor.visitListener(StandardDescriptorProcessor.java:1956)
... 25 more
色々と調べてみると、本家に issue がありました。
Jenkins 2.54 causes java.lang.UnsupportedClassVersionError
なるほど、Java 8が必須になったのですね。
確かに、EC2 の Amazon Linux はデフォルト Java 7 です。
と言うわけで、Javaのアップデートをしていきます。
まずは現在のバージョンを改めて確認してみます。
$ java -version java version "1.7.0_131" OpenJDK Runtime Environment (amzn-2.6.9.0.71.amzn1-x86_64 u131-b00) OpenJDK 64-Bit Server VM (build 24.131-b00, mixed mode) $ yum list installed | grep java java-1.7.0-openjdk.x86_64 1:1.7.0.131-2.6.9.0.71.amzn1 installed javapackages-tools.noarch 0.9.1-1.5.amzn1 installed tzdata-java.noarch 2017b-1.69.amzn1 installed
Java 7 である事が確認出来たので、次は Java 8 にアップデートします。
$sudo yum install java-1.8.0-openjdk-devel
alternatives でバージョンを切り替えます。
$ sudo alternatives --config java 2 プログラムがあり 'java' を提供します。 選択 コマンド ----------------------------------------------- *+ 1 /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java 2 /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:2
念の為、適用されているバージョンを確認します。
$ java -version openjdk version "1.8.0_121" OpenJDK Runtime Environment (build 1.8.0_121-b13) OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)
無事にアップデート出来たので、Jenkinsの再起動を行います。
再起動は
http://[ホスト名 or IPアドレス]/safeRestart
に接続する事で、簡単に行う事ができます。
これで無事に接続できました。
アップデートの度にこんな思いするのは、本当辛いです。
2017年4月2日日曜日
Redmine チケットの状態変更をSlackに連携する
4月 02, 2017
オフィス狛 技術部です。オフィス狛では、社内の連絡に関してメールは使わず、全てSlackでやり取りしています。
ただ、Redmineに関してはデフォルトだとメール通知しか出来ないので、
Redmineの為だけにメールチェックを行う事が必要になってしまいます。
このメールチェックをやめたい、という事で、
Redmineでチケットが登録・編集された際に、Slackへ通知するようにしていきます。
まずは、Slackのチャンネル作成、Slack側のアプリ作成作業を行う必要があるのですが、
この辺の作業は、下記を参照下さい。
AWS EC2 にインストールした GitLab と Slack の連携
という事で、この先は、Slackのチャンネル作成(今回は、「#redmine-notification」というチャンネルを作成)が完了していて、
且つ、Slack側のアプリ作成〜Webhook用のURL取得済みとして、進めて行きます。
1)redmine_slack(プラグイン)のインストール
まずはRedmineのプラグインをインストールします。$ cd /var/lib/redmine/plugins $ git clone https://github.com/sciyoshi/redmine-slack.git redmine_slack $ bundle install $ rake redmine:plugins:migrate RAILS_ENV=production $ touch /var/lib/redmine/tmp/restart.txtここでは、redmineのホームディレクトリが「/var/lib/redmine」の場合を想定しています。
「restart.txt」を作成しておく事で、apacheの再起動無しで、Redmineの再起動を行う事ができます。
(ファイル作成後に、ブラウザでRedmineに接続した時に再起動が行われます。)
正しくインストールされていると、Redmineの「管理 > プラグイン」から、以下のように確認出来ます。
2)カスタムフィールドの作成
続いて、Redmineの「管理 > カスタムフィールド」で「プロジェクト」を選択し、新しいカスタムフィールドを作成します。
名称は「Slack Channel」にしておきます。
3)redmine_slack(プラグイン)の設定
Redmineの「管理 > プラグイン」から、Redmine Slackの「設定」を選択します。以下のような設定画面が出てくるので、
Slack側のアプリを作成した際のWebhook用URLを入力します。
今回は、チケットの更新のみを連携の対象としています。(「Post Issue Updates?」にチェックを付けている)
そして、先ほどカスタムフィールドの名前を「Slack Channel」にした意味がここで分かります。
redmine_slackは、デフォルトだと、全プロジェクトで共通な一つのチャンネルのみ連携が出来ます。
その連携先チャンネルをプロジェクト単位で決めたい場合は、
カスタムフィールドで「Slack Channel」を作成する必要があります。
ちなみに、プラグイン設定の方の「Slack Channel」は必須項目で、
指定無しには出来ないので、「-(半角ハイフン)」を設定しています。
4)Redmine各プロジェクトごとの設定
プロジェクトの「設定 > 情報」を表示すると、追加したカスタムフィールドが出てくるので、ここに、Slackのチャンネル(今回は、「#redmine-notification」)を入力します。
これで、このプロジェクトのチケットが変更された際、Slackへの連携が可能になります。
備考:連携の際に気を付ける事
弊社の場合、Git(GitLab)のリポジトリにPushした際にSlackへ通知が飛び、同時に、リポジトリへの変更がRedmineが参照しているリポジトリへ連携されるようになっています。
つまり、コミットコメントなどで、Redmineのチケットの状態を変更するような記載(「fixes #xxxx」とか)をすると、 Slackの通知が2回飛ぶ事になってしまい、これが開発繁忙期になると、通知がピーピー鳴りまくるので、 通知が必要なプロジェクトを見極める必要があります。
弊社では、お客様とのやりとり(バグトラッキング)で、通知は漏れなく欲しい場合、
そして、そのプロジェクトでGitのリポジトリを参照していない場合のみ、
今回のような設定を行なっています。
2017年3月25日土曜日
AWS EC2上のGitLabリポジトリを別サーバーのRedmineから参照する
3月 25, 2017
オフィス狛 技術部です。早くもGitLab のインストール・設定シリーズ第5回目となります。
第3回でリポジトリを移行した結果、ある問題が発生しました。
移行前のリポジトリは Redmine がインストールしてあるサーバーに存在したので、
Redmine からリポジトリを参照出来たのですが、別サーバーに移行したら参照する事が出来なくなりました。
そう、「Redmineは、自サーバーにあるリポジトリのみ参照可能」なのです。
折角 GitLab に移行したのだから、GitLab の issue を使う、という事も考えたのですが、
Redmine の工程管理(チケット)とリポジトリの関連付けはやっぱり便利なんですよね・・・・。
というわけで、今回は、AWS EC2 上の GitLab リポジトリを Redmine から(間接的に)参照出来るようにしたいと思います。
その他の記事は、以下をご覧下さい。
第1回(AWS EC2 に GitLab をインストールする)
第2回(AWS EC2 に GitLab をインストールする(メールの送信テスト編))
第3回(AWS EC2 の GitLab へリポジトリを移行する)
第4回(AWS EC2 にインストールした GitLab と Slack の連携)
1)GitLab のリポジトリをクローンする
現在、メインのリポジトリは、GitLab側のEC2(サーバーA)になるので、そこから、Redmine側のEC2(サーバーB)へリポジトリをクローンします。
【注意】クローンする場所(ディレクトリ)に対しては、Redmine が動作しているWebサーバー(ここではApache)が参照権限を持っている必要があります。
では、サーバーAのリポジトリをクローンします。
sshで接続するので、サーバーAの鍵が必要になります。鍵は、「/home/[ec2_user]/.ssh」に格納します。
※[ec2_user]は、サーバーBにログインしているユーザーで置き換えて下さい。
そして、コマンドを簡略化させる為に、同じディレクリに「config」というファイルを作成し、
Host gitlab_git User git HostName gitlab.hogehoge.co.jp IdentityFile ~/.ssh/keyname上記の内容を記述します。
Host : コマンドに含める簡略名になります。
User : 接続するサーバーのユーザー
HostName : 接続するサーバー
IdentityFile : 使用する鍵
これで準備が出来たので、早速クローンします。
$ git clone --bare ssh://gitlab_git/hogehoge-dev/RipoTest.git「hogehoge-dev」はGitLab側のユーザー or グループになります。
クローンしたリポジトリは、対象となるRedmineプロジェクトから「設定 > リポジトリ」で参照出来るように設定しておきます。
2)redmine_github_hookのインストール
ここでRedmineのプラグインをインストールします。$ cd /var/lib/redmine/plugins $ git clone git://github.com/koppen/redmine_github_hook.git $ touch /var/lib/redmine/tmp/restart.txtここでは、redmineのホームディレクトリが「/var/lib/redmine」の場合を想定しています。
「restart.txt」を作成しておく事で、apacheの再起動無しで、Redmineの再起動を行う事ができます。
(ファイル作成後に、ブラウザでRedmineに接続した時に再起動が行われます。)
正しくインストールされていると、Redmineの「管理 > プラグイン」から、以下のように確認出来ます。
3)GitLab の Webhooks の設定
続いて、GitLab側で Webhooks の設定を行います。連携したいプロジェクト(リポジトリ)を選択し、右上の歯車プルダウンから「Webhooks」を選択します。
そして、次の設定画面のURLに
http://redmine.hogehoge.co.jp/github_hook?project_id=redmine_identifierのように入力します。それぞれの環境に合わせて、「redmine.hogehoge.co.jp」と「redmine_identifier」を変更してください。
redmine.hogehoge.co.jp : Redmine側のEC2(サーバーB)のドメイン or IPアドレス。
redmine_identifier : Redmineにおけるプロジェクトの識別子
Triggerも適宜チェックつけますが、単純な連携であれば、Pushだけでも良いかもしれません。
これで、GitLabへのPushはRedmineが参照しているリポジトリに連携され、常に最新状態が保てる事になります。
(何だか二度手間になっている感は拭えないですが)
2017年3月12日日曜日
AWS EC2 にインストールした GitLab と Slack の連携
3月 12, 2017
オフィス狛 技術部です。GitLab のインストール・設定シリーズ第4回目の今回は、Slack との連携を行います。
その他の記事は、以下をご覧下さい。
第1回(AWS EC2 に GitLab をインストールする)
第2回(AWS EC2 に GitLab をインストールする(メールの送信テスト編))
第3回(AWS EC2 の GitLab へリポジトリを移行する)
では、早速やり方を説明して行きますが、前回までと違い、今回はブラウザ側の設定で完結出来ます。
1)通知用のチャンネルを作る(Slack側作業)
1-1) 作業の目標はGitLabへのPushをSlackに連携する事なので、何はともあれ通知用のチャンネルを作成します。

2)通知用のアプリを作る(Slack側作業)
2-1) Slackのメイン画面で、チーム名の横にある「下矢印」をクリックし、メニュー表示後、「Apps & integrations」を選択します。

2-2) 新たに表示された画面の右上「Build」をクリックします。

2-3) さらに新たな画面に遷移するので、そこで画面中央の「Start Building」をクリックします。

2-4) 続いて、アプリ名を入力し、通知するチームを選択してアプリを作成します。

2-5) アプリが作成されるので、アプリの種類として「Incoming Webhooks」を選択します。

2-6) 「Incoming Webhooks」の設定画面になるので 、まず右上のスイッチを「ON」にし、
その後、「Add New Webhooks to Team」をクリックします。

2-7) 通知を行うチャンネルとして、先程作成したチャンネルを選択し、「Authorize」をクリックします。

2-8) 先程の画面に戻りますが、Webhook用のURLが表示されるので、これをコピーしておきます。

3)通知の設定を行う(GitLab側作業)
ここからは、GitLab側での設定になります。3-1) 管理者でログインし、管理トップの画面から、右上の歯車から「Service Templates」を選択します。

3-2) Slackを選択

3-3) まず設定を有効にする為、「Active」にチェックを付けます。
後は、どのトリガーで通知を行うか設定します。
下記画像だと、「Push」、「Merge request(GitHubで言う所のPullRequest)」「Tag push」の時に、
「gitlab-notification」へ通知するようにしています。

そして、先程コピーしておいたWebhook用のURLを設定し、「Save」します。
※「Service Templates」で設定しておくと、全てのプロジェクトに反映されるので、便利です。

3-4) 続いて、各プロジェクトで設定を確認してみます。
プロジェクトのトップ画面で、右上の歯車から「Service」を選択します。

3-5) Slackを選択します。
※「Service Templates」で Activeにしているので、緑のマーク(有効マーク)が付いているはずです。

3-6) 設定自体は、「Service Templates」と同じになっていると思いますので、
「Test setting」を押して、通知のテストをしてみましょう。

3-7) 下記のようなメッセージがSlackに出てくれば成功です。
(テスト通知の場合、直近のPush情報が通知されるようです。)

※ちなみに、Slackに表示される画像と名称は、Slack側のアプリ側で変更可能です。
上記は変更後の状態です。
何も設定していないと、Slack API のアイコンが表示されるはずです。
以上です。
開発初期などは、通知が飛び交う事になるので、ちょっとウザいと感じるかもしれません。
(弊社でも最初はそう感じました)
ただ、慣れてくると、誰がいつどんなPushを行なったのか、どの不具合の修正が行われたのか、
など、かなり有意義に思えてきます。
特に、管理する立場から言うと、進捗状況がリアルタイムで分かるのは、かなり助かります。
余談(設定方法はコロコロ変わる)
実は、この記事は、少し前に記載は終わっていて、後は公開するだけの状態でした。今回、公開しようと思って、情報の確からしさをチェックしたら、
Slack側の設定方法がガラッと変わっていた為、
書き直しをする事になってしまいました。
ブログの記事は寝かしちゃいけないな、と反省しました。
登録:
投稿 (Atom)