2020年2月21日金曜日

SVNサーバーをヘテムルサーバーに移設


SVNサーバをヘテムルサーバに移設


ヘテムルサーバから転送量制限の緩和メールが届いたのと、SVNサーバを置いているさくらVPSがちょっと重かったので、SVNサーバを移設してみました。

少しハマってしまったので、まとめておきます。

リポジトリを最新に

いちおう、移設前にローカルコンピュータ上の内容とリポジトリを一致させておいたほうがいいと思いましたので、コミットしておきました。


ローカルコンピュータ上では TortoiseSVN を利用してます。

リポジトリの退避

移設前のサーバー上のリポジトリを退避(バックアップ)します。

バックアップには svnadmin dump コマンドを使用します。

リポジトリをどこに作ったか忘れてしまってたので探すのに苦労したw

ls /var/svn/repos/ に発見しましたw



まず、移設前の環境でリポジトリをバックアップします。


SSHなどでサーバーにログイン。


作業ディレクトリを作ります。


(dfなどでディスクのサイズを確認しておきましょう)


# cd /tmp
# mkdir back
# cd ./back

現在のリポジトリの内容をダンプします。

# svnadmin dump /var/svn/repos/PROJECT > ./PROJECT.dump 2>/dev/null


標準エラー出力をリダイレクトしておかないと、すごい量のダンプが出力されて、そのうち印刷データなどに飛ばされるようなことになりかねます(実際そうなったw)ので、標準エラー出力を止める必要があります。

2>/dev/null

書いてないと時間もかかるしkillできないしで、めちゃくちゃ待たされますw

終わったらダンプファイルを圧縮します。

tar -zcvf PROJECT.dump.tar.gz PROJECT.dump

圧縮したダンプファイルを移設先にコピーします。

バックアップ目的でローカルコンピュータを経由してもいいけど、普通にscp で転送したほうが楽ですね。

まず移転先のヘテムルサーバに SSHでログインして、tmp フォルダを作っておきます。


# ssh -P 2222 ユーザー名@SSHドメイン

# mkdir -p ./tmp

# scp -P 2222 PROJECT.dump.tar.gz ユーザー名@SSHドメイン:/home/sites/heteml/users/h/o/g/hoge/tmp/

※ /home/sites/heteml/users/h/o/g/hoge を付けとかないとだめなのがミソw

ダンプファイルの解凍

ヘテムルサーバにログインしてダンプファイルを解凍します。


# cd ./tmp
# tar -zxvf PROJECT.dump
# cd ..


リポジトリを作成します。


# mkdir -p ./repos
# svnadmin create ./repos/PROJECT


リポジトリをダンプファイルから復元(リストア)

# svnadmin load ./repos/PROJECT < ./tmp/PROJECT.dump 2>/dev/null

これでリポジトリ構成が移設できます。


Windows上の TortiseSVN でリポジトリの再配置

※ここが最も苦労しました。SSHのポート番号が 2222 なのと、リポジトリのパス名指定がややこしいからでした。


まず、C:\ユーザー\ユーザー名\AppData\Roaming\Subversion\config ファイル
を開き、[tunnels]セクションに以下を追加します。



repos = "C:\\Program Files\\TortoiseSVN\\bin\\TortoisePlink.exe" -ssh -P 2222 -l ユーザー名 -pw パスワード
            ↑ '\\'と2つ付けないとダメでした。場合によっては空白部分にも '\ 'が必要と記載されている場所もありました。
↑小文字でなければいけないし、'_' などは使用できないようでした。


エクスプローラからローカルフォルダを右クリックし、TortizeSVNメニュー
の再配置を選択し以下のように記載します。

svn+repos://SSHサーバー/home/sites/heteml/users/h/o/g/hoge/repos/PROJECT

再配置が完了すれば、移設がうまくいったことになったと思ったら大間違い。

ちゃんと更新とかコミットを確認しないと大変なことになります。

更新がうまくいかなかった場合の対処について

リビジョンが 73 なのに 173 のリビジョンなんてない!というエラーで更新
ができなくなってしまいました。


対応としてやったこと

(1) リポジトリが正しいかを確認。

別のフォルダを作って、対象のリポジトリをチェックアウトしてみます。

うまくいかない場合はサーバー側のリポジトリに問題があります。

うちの場合は正しくチェックアウトできました。


(2) ローカルフォルダの .svn フォルダを削除します。

勇気のいる行動ですねw真似をされる場合は自己責任でお願いします。

(3) リポジトリをチェックアウトします。

フォルダが空でないよと警告出ますが、リポジトリを本来のローカルフォルダ
にチェックアウトします。


※(1)で新しく作成したフォルダにチェックアウトしたのち古いフォルダ
と名前を変更してしまえばいいと思いましたが、それはできませんでしたw

上記手順でうまくいきました。

めでたしめでたし。

さいごに

古いサーバーのリポジトリやダンプは削除しておきましょう。

svnadmin にはリポジトリを削除する機能が用意されていないので、

# rm -rf /var/svn/repos/PROJECT で削除します。

なかなか時間のかかる作業でした。



2019年10月8日火曜日

WEBサイトの国際化、多国語化を実現する slang.js

「IT後進国」とまで言われるようになった日本ですが、いろいろな原因や要素があるのだと思います。
エコノミストではありませんので具体的な指摘なんかできないんですが、いわゆる『ホームページ』というのに、その片鱗があるような気がします。

お仕事でお役所とか企業様とかの『ホームページ』を編集したりすることがあるのですが、多くの方が、必要な情報を『ホームページ』に掲載した時点で(広く)公開した気になっていらっしゃいます。
実際には、メンテナンスしたページを一般の方が目にすることになるのかどうかはわからないのに。

『ホームページ』の意義とか役割を考えると、むしろ、商品やサービス、技術を広く公開できてナンボという世界だと思うのです。

日本の人口から考えると、日本語のWEBサイトを見てくれるのは、ほとんどが日本人になりますね。
海外でどのような言語が使われているかを考えると、英語でのWEBサイト提供は、これから先必須になってくると思います。

もちろん、諸外国からのアクセスでも、google翻訳がとっても役に立つようになっているのは事実です。

翻訳エンジンの精度は以前に比べるとものすごく素晴らしくなっています。
日本語のWEBサイトを英語や中国語に翻訳するのも、google のAPIを使って、すこぶる簡単に実現できる時代になっていますね。

まーでも、コンテンツの内容がどのように変換されるのかを担保できないというスタンスでは、WEBサイトを google翻訳に頼ってしまうことには躊躇する担当者も多いのではないでしょうか?
どこぞの国で書かれたマニュアルなんかが笑いものにされていたのと同じような世界になるのは避けたいものです。

そこで、WEBサイトを他国語に翻訳できるような仕組みがないものかと探してみましたら、こんなのを見つけました。

http://www.openxrest.com/translatejs/
(日本語の解説サイト)
https://webkaru.net/jquery-plugin/translate/

WEBサイトの訪問者は、言語選択ボタンでお好みの言語に変えてもらう、というおなじみの形式です。
そこ、なんか違うなーと思うんです。

英語版のOSで英語版のブラウザを使ってサイトを訪問してくる方って、英語でページを見たいと思うと思います。
日本語なんか読めませんし、どうかすると文字化けしてるかもしれません。
そんなページの右上に「English」と書かれたボタンみたいなところを見つけてクリックしてくれると、そこで初めて自分にも読める文章が現れる、というスンポー。
あまり良いインターフェースとは思えないんですね。

ブラウザに使用言語の設定があって、javascriptで取得できるようになってますから、そいつを利用するようにすれば問題解決です。

それに、上記の translate.js を使う場合、同一コンテンツの中に複数の言語リソースを含めなきゃいけないのもメンテナンス性を損なってると思うんです。

WEBサイトを英語で記述しておいて、ブラウザで設定される言語が英語以外の場合、対象となる翻訳情報を読み込んで表示させる。
そんな仕組みがあってもいいんじゃないでしょうか。


ということで、javascriptを使って書いてみました。

slang.js

今、会社の膨大なページをコツコツと英語に対応しようとしてます・・・

2019年7月30日火曜日

VisualStudioで既存のフォルダをプロジェクトに追加する

諸事情で(謎)、VisualStudio 2015 を使い続けてます。
他のプロジェクトをコピーして新しいプロジェクトとして再構築しようとする際にフォルダ配下のファイルをプロジェクトに追加するとフォルダーなしでプロジェクトに追加されてしまいます。

でもって、新規フォルダで同名のフォルダを追加しようとするとエラー。

WEBを検索すると、エクスプローラからソリューションエクスプローラにフォルダをドラッグ&ドロップするとうまくいくとの記述を見ますが、こちらの環境ではうまく動いてくれません。

ということで、以下の手続きでフォルダを追加しました。

1.VisualStudio を終了
2.目的のプロジェクトの .csproj ファイルをエディタで開く
3.以下の記述を追加
<ItemGroup>
<Folder Include="フォルダ名\" />
</ItemGroup&lgt;
4.保存終了して .sln を開く。

無事フォルダが追加されます。
既存ファイルを追加すると、上記の Folder Include は消えてなくなります。

本題に関係ありませんが、エクスプローラがとてもよく落ちてしまうようになって、ストレスまっくすな状態です。
こっちを何とかしたいw

2019年6月11日火曜日

XML HTTP Request status 12157

WEBサーバーへの問合せにXML応答をするよう構築しているのですが、とある企業様から
Response status:12157
と表示されてエラーになる!とのご指摘がありました。

10,000を超えるユーザーが同じ処理を利用しているのに、この企業様のコンピュータからはエラーが表示されて失敗するとおっしゃるのです。
そこで HTTP Request 12157 のキーワードでいろいろと調べてみますと、最終的にこの部分が該当するのではないか、となったわけです。

https://support.microsoft.com/ja-jp/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi

ところが、企業様ではTLS 1.1, 1.2 ともに有効だから関係ない!とおっしゃる。

さらに調べると、公開鍵や秘密鍵のやり取りうんぬんが必要とか出てきて、わけわかめ状態になってしまいました。

企業様に、APIのあるサイトにテストCGIを用意してアクセスをお願いしてみましたら、原因がわかりました。

WEBサーバーのアドレスがファイアウォールのブラックリストに追加されていたのだそうです。

ホワイトリストに追加していただくことで問題が解決しました。

でも、ちょっと待て!
なぜにうちのサーバーがブラックなの?
とお問い合わせしてみましたら、「パークドメイン」だからなのだそうです。

たしかにAPI専用のサーバで、WEBコンテンツは公開してないけど・・・
今後のためにWEBコンテンツを配置しておいたほうがいいのかな・・・

2019年1月21日月曜日

Perl uri_unescape で文字化け

実は文字化けにはその後も苦しんでおりまして。
原因となる現象をようやく突き止めましたのでサンプルプログラムを公開しますね。

use Carp::Heavy;
use strict;
use URI::Escape;
use Encode;
use encoding 'utf-8';

my $a1 = '%E8%A9%A6%E9%A8%93';
my $b0 = '試験';
my $b1 = uri_escape_utf8($b0); #内容は '%E8%A9%A6%E9%A8%93'
print("$a1\n");
print("$b1\n");
print("1\n") if($a1 eq $b1);    #当然のごとく1が出力される

my $a2 = uri_unescape($a1);
my $b2 = uri_unescape($b1);
print("1\n") if($a2 eq $b2);    #なぜか 1 が表示されない
print("$b2\n"); #こちらは '試験'
print("$a2\n"); #文字化け
exit;


use encoding 'utf-8' を取ったり use utf8; にしたりすると他所に
大影響が出てしまうため変更できません。

これ。本当にハマりましたよ。
いったい何がどうなっているのかさっぱりわかりませんでした。

※実際には CGI 上のパラメータが文字化けしてました。

上記の謎の動作ですが
$a1= encode_utf8($a1);
を呼び出すことで期待通りの動きをすることがわかりました。

さて、本番環境に対応しようと・・・
my $cgi = new CGI();
my $a2 = $chi->param('a2');
文字化けです。
CGI の sub new で取得するuri_encode されたパラメータに対して事前に
encode_utf8を実行しなければならないのに、POSTリクエストだから標準
入力を変更する術が見つかりません。

じゃあ、ってことで呼び出し側を GET にしましたら、なんの変更も加えず
文字化けしなくなりましたよ。
Perlモジュールのバージョンの影響かと思い、さんざん調査すること3日
こういうのって、あっけなく解決するもんなんですねぇ
あー眠たい。

2018年12月30日日曜日

perl CGI HTML::Template で文字化け

Perl CGI での文字化け問題は何年も前に解決させたはずだったのですが(以前は Perl + Template の場合)
新しい CentOS (サーバに無料で入ってる Ver 6)の環境で、現在動作しているcgiを実行すると文字化けしてしまう現象に悩まされました。

ハマった手順を書いてみますね。

1)httpd.conf の変更
文字化けはこれでなおる!とネット上のあちこちに書いてあります。
# vi /etc/httpd/conf/httpd.conf

AddDefaultCharset off
または
#AddDefaultCharset off コメントアウト。


動作結果:NG
世界中でほとんど解決しているらしいのですが、うまくいきません。

2)php.ini の変更
# vi /etc/php.ini

;default_charset = "UTF-8"

default_charset = ""
に変更


動作結果:NG
そもそも php 使ってませんし。

ここでブラウザ側のレスポンスヘッダを確認してみますと utf-8 となっていました。
んー?なのに文字化け?理解できないぞ・・・

ちなみに、cgi のソースや HTML, CSS, JS, テンプレートファイルなど、すべてのファイルは UTF-8 で記述してます。(改行は LF)
なぜだろう、と、試験を実施することに。


3)簡単なHTMLを用意
[test.html]

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>テストページ</title>
    </head>
    <body>
        UTF-8で記述されたページ
    </body>
</html>


動作結果:なんと、うまく表示されます。

4)cgi だとダメなのかな?
[test.cgi]

#!/usr/bin/perl --
print "Content-Type: text/html; charset=utf-8\n\n";
print "<html><body><div>\n";
print 'クオート文字';
print '<br>';
print "ダブルクオート文字";
print '<br>';
print "<div></body></html>\n";
exit;

クオートとダブルクオートで分けたのは、 perl の動作で文字化けしているのかどうかを確認するためです。

動作結果:なんと、うまく表示されます。

5)HTML::Template が怪しい。
どうやら使用している HTML::Template が怪しいのではないかとあたりを付けて検索したら情報がありました。
HTML::Template 2.98 で UTF問題が解決してる!というのです。
移行先のサーバーの HTML::Template は Ver,2.97 です。
ちなみにうまくいっていた旧サーバーの HTML::Template は Ver,2.94 でした。

Ver 2.98 のソースはここにありました。
https://github.com/mpeters/html-template

CPAN からのインストールしかやったことないので、git からどうやってインストールするのかわからずw
ダウンロードした HTML/Template.pm, HTML/Template/FAQ.pm をそのまま perl5 のファイルに上書きw

文字化けする cgi を動作させてみました。

動作結果:NG
ここまで、大量に時間を食ったにもかかわらず、うまくいかないとは・・・

6)binmode => 'utf8' を記述
既存 cgi の new HTML::Template 構文で、binmode => 'utf8' を追加する、との記述があったので
試してみました。

動作結果:NG
この記述は、上記リンクをたどる際に対応したパッチを当てたソースの場合に有効だったもので、動かないことは予想できていました。

7)utf8 => 1 を記述
HTML/Template のドキュメントを読み、new 構文の utf8 オプションがあることを発見。(旧サーバにはないオプションでした。)

既存 cgi の new HTML::Template 構文で、utf8 => 1 オプションを追加して実行してみました。

my $tmpl = HTML::Template->new(die_on_bad_params => 0, filename => $file, utf8 => 1);

動作結果:おお!!!!ようやく文字化けせずに表示されました!

しかしながら、問題があります。
既存プログラムの cgi ファイルは山のようにあります。
その全部にフラグを追加するのは困難ですよ。
デグレードなんか発生させちゃった日にゃ目も当てられません。
なんとかならないかな・・・

8)HTML::Template を編集。
perl5 の HTML/Template.pm を開いてみると、次のような部分なありました。

my %OPTIONS;
BEGIN {
    %OPTIONS = (
        debug                       => 0,
        ;
        utf8                        => 0,
        ;

ええい、こいつを1にしてしまえ!

        utf8                        => 1,

と変更した後で、既存の cgi に戻して動作

動作結果:OK

文字化けが解消されました!!!

モジュールの挙動が変わるなんて、ほんと困りものです。

2018年10月15日月曜日

マルチディスプレイ環境で親ウィンドウの中心にウィンドウを表示するには

表題の通りです。

親ウィンドウの中央にダイアログなどを表示しようとすると、親ウィンドウそのものが画面から外れている場合に表示領域外に表示されてしまったりして困ったことになります。

マルチディスプレイ環境だったりすると、座標域に負数が含まれる場合などもあって、なかなかややこしい。

WEB上を検索しても、GetSystemMetrics(SM_CXSCREEN)とかGetSystemMetrics(SM_CXSFULLCREEN) などを使ったサンプルしか公開されていなくて、ちょっと不満だったので書いてみました。

ま、実際にはもっとややこしい環境もあると思うので完全ではないかもしれないけど、うちの環境では表示されるのでよしとしようw

ヘッダファイルの記述

extern BOOL SetWindowCenterParent(HWND handle, HWND parent, int width, int height, int min_width = -1, int min_heigh = -1);

ソースファイル

#include 
//
// ウィンドウを親ウィンドウの中心に表示する
//
// 【パラメータ】
//  HWND handle     対象となるウィンドウハンドル
//  HWND parent     親ウィンドウハンドル(HWND_DESKTOP も可)
//  int width       ウィンドウの幅
//  int height      ウィンドウの高さ
//  int min_width   最小ウィンドウ幅(不要な場合は負数を指定)
//  int min_heigh   最小ウィンドウ高さ(不要な場合は負数を指定)

BOOL SetWindowCenterParent(HWND handle, HWND parent, int width, int height, int min_width, int min_heigh)
{
 // 親ウィンドウの中心を取得
 RECT parent_rect;
 GetWindowRect(parent, &parent_rect);

 POINT center;
 center.x = (parent_rect.right + parent_rect.left) / 2;
 center.y = (parent_rect.bottom + parent_rect.top) / 2;

 // ディスプレイ情報
 SIZE display;
 display.cx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
 display.cy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
 
 // タスクバーの大きさを調整
 SIZE screen;
 screen.cx = GetSystemMetrics(SM_CXSCREEN);
 screen.cy = GetSystemMetrics(SM_CYSCREEN);
 RECT work_area;
 SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0);
 SIZE task_bar;
 task_bar.cx = screen.cx - (work_area.right - work_area.left);
 task_bar.cy = screen.cy - (work_area.bottom - work_area.top);
 display.cx -= task_bar.cx;
 display.cy -= task_bar.cy;

 POINT origin;
 origin.x = GetSystemMetrics(SM_XVIRTUALSCREEN);
 origin.y = GetSystemMetrics(SM_YVIRTUALSCREEN);

 // 最小サイズ、最大サイズの検査
 if ((0 < min_width) && (width < min_width))
 {
  width = min_width;
 }
 if ((0 < min_heigh) && (height < min_heigh))
 {
  height = min_heigh;
 }
 if (display.cx < width)
 {
  width = display.cx;
 }
 if (display.cy < height)
 {
  height = display.cy;
 }
 // 表示位置
 POINT place;
 place.x = center.x - (width / 2);
 place.y = center.y - (height / 2);

 // ディスプレイの座標範囲(マルチディスプレイ含む)からのはみだし検査
 if ((origin.x + display.cx) < (place.x + width))
 {
  place.x = origin.x + display.cx - width;
 }
 if (place.x < origin.x)
 {
  place.x = origin.x;
 }
 if ((origin.y + display.cy) < (place.y + height))
 {
  place.y = origin.y + display.cy - height;
 }
 if (place.y < origin.y)
 {
  place.y = origin.y;
 }
 return SetWindowPos(handle, HWND_TOP, place.x, place.y, width, height, 0);
}