はじめに
Movable Type 7が出るまでは、PowerCMSを使っていました。お値段は、お高いのですが・・・
一通りの機能がすでに、パッケージされているので、案件途中に大幅変更があっても、追加費用が掛からないことがおおいので
なかなか、見積後の、増額ができないときに助けられました。
最近はMovable Type 7でコンテンツタイプが出たことで、Movable Type 7を使うことが多くなり、途中で編集サーバーと公開サーバーにと・・・
PowerCMSではPowersyncがあるのですが・・・・・・
Movable Typeではアドバンス版に内蔵されていますが・・・。
Wordpressと違って、システムファイルと、静的ファイルが分離できるので、編集ファイルをイントラネットで置けば、セキュリティ度はあがるかな・・
ファイル同期の調査してみる。
同期にはrsync ftp lftpが検討できる。
rsyncは、公開サーバ側に、rsyncを別途入れたり、証明書だったりと、公開サーバ側にも設定が必要・・・
ftpは差分が・・・
lftpかな・・lftpもインストールされていませんが、編集側にインストールするだけで。公開側はFTPサーバが公開されている必要があります。
ロジックは・・
Movable Typeの場合、絶対パス・・PowerCMSだと、Abs2Relで解決だったけど・・
あと、月のアーカイブだと。2020/11/とか階層が。。。
なのでドメインを下記に決める
stg.編集サーバードメイン名
www.公開サーバードメイン名
linux grep&sedでなんとかなりそう。
編集サーバーのHTMLを直接変更すると、編集サーバーでプレビューできないので
テンポラリーディレクトリにすべてコピーして、grepすれば問題なさそう。。
ただ、HTMLがすべて更新されてしまうので、lftpにしても全部のファイルが・・上書き・・画像とか重たいのは問題なさそう。
あとは、ページが削除された場合の対応は、lftpの--delete とかで、同期先は削除されるみたいなので、
テンポラリーディレクトリにコピーする前に、テンポラリーディレクトリの内容をコピー前に削除すればよいか・・・
ただ、ディレクトリのパーミッション操作などは、権限が必要そうなのでディレクトリ毎削除せず、中身だけ削除にする。
問題点
フォームなどのシステムがある場合。どうするの?
MTのシステムフォルダーとか。転送する?
Powersyncみたいに、個別ファイルの選択可能と転送スケジュールは?
記事の公開日指定の場合
シェルで書いてみた。
mirrorのコメント部分は、lftpのコマンド--dry-runを使用。これは事前のテストができます。--deleteコマンド使うと、消したくないものまで
消えるので、事前にテストしてくださいね。
rmのコメント部分は、MTのシステムフォルダーが不要か、削除かの場合
cronで1時間毎に起動できるかな・・
#!/bin/bash
REMOTE_SERVER='ftp://公開サーバーのURL、IP
USER='公開サーバーのユーザーID'
PASS='公開サーバーのパスワード'
BASE_DIR='/var/編集サーバーの公開パス/*'
REMOTE_DIR='/var/公開サーバーパス/'
TEMP_DIR='/var/編集サーバーの一時ディレクトリパス/tmp/'
LOG_DIR="/var/編集サーバーのログ用ディレクトリパス/tmp/lftp_$(date +%Y%m%d%H%M).log"
rm -rf ${TEMP_DIR}/*
chmod 0777 -R ${TEMP_DIR}
cp -a ${BASE_DIR} ${TEMP_DIR} 2>&1
#
#rm -rf ${TEMP_DIR}/mt/
find ${TEMP_DIR} -type f \( -name \*.html -or -name \*.css -or -name \*.js -or -name \*.xml \) -print0 | xargs -0 grep -l www.公開サーバードメイン名 | xargs sed -i 's/www.公開サーバー/stg.編集サーバードメイン名/g' 2>&1
/usr/bin/lftp <<EOF
set ssl:verify-certificate no
open -u ${USER},${PASS} ${REMOTE_SERVER}
#mirror --dry-run --reverse --delete --only-newer --no-perms --no-umask --log=${LOG_DIR} ${TEMP_DIR} ${REMOTE_DIR}
mirror --reverse --delete --only-newer --no-perms --no-umask --verbose --log=${LOG_DIR} ${TEMP_DIR} ${REMOTE_DIR}
echo end
close
quit
EOF
説明
テンポラリーのディレクトリ内をすべて削除
編集サーバーの公開ディレクトリ内をタイムスタンプ等保持してコピー
コピー後、不要なファイル削除
find & grep & sedで編集ドメインを公開ドメイン変換、
sedしてしまうと、変換がなくても、タイムスタンプが変わってしまうので、findオプションで編集する拡張子を指定
lftpで差分を転送
lftp部分をrsyncにすれば、改造できるかな。。
再構築が完了したら、手動でシェルで実行
シェルってなに??
黒い画面でコマンド打つのって・・こわい・・・汗
上記の方用に
シェルをMovable Typeで実行できるようにプラグインを作る?
ぐは・・・
プラグイン構成
下記構成を作り、pluginsフォルダーへCMDEXECフォルダー毎コピーします。
CMDEXEC--+--lib---CMDEXEC--+--L10N---ja.pm
| +--L10N.pm
| +--CMS.pm
+--tmpl--+--config_template.tmpl
| +--view.tmpl
+--config.yaml
config.yamlの内容
id: cmdexec
key: MT::Plugin::CMDEXEC
name: CMDEXEC
version: 0.1
author_name: 電脳職人村
doc_link: http://www.omakase.net
author_link: http://www.omakase.net
description: <MT_TRANS phrase='description of CMDEXEC'>
l10n_class: CMDEXEC::L10N
blog_config_template: config_template.tmpl
settings:
cmd_enabled:
default: 0
cmdline:
default: /home/www/xxx.sh
log_save:
default:
applications:
cms:
menus:
tools:cmd_website:
label: cmd exec
order: 10021
mode: cmd_view
view:
- website
- blog
condition: $CMDEXEC::CMDEXEC::CMS::menu_permission
methods:
cmd_view: $CMDEXEC::CMDEXEC::CMS::view
cmd_run: $CMDEXEC::CMDEXEC::CMS::do_run
L10N.pmの内容
package CMDEXEC::L10N;
use strict;
use base 'MT::Plugin::L10N';
1;
ja.pmの内容
package CMDEXEC::L10N::ja;
use strict;
use base 'CMDEXEC::L10N::en_us';
use vars qw( %Lexicon );
## The following is the translation table.
%Lexicon = (
# config
'description of CMDEXEC' => 'コマンドラインを実行します。',
'cmd enabled:' => 'プラグインを利用する',
'Run cmd:' => 'コマンドラインのPath(必須)',
'Log Save:' => 'MTのログに保存する',
'Hint enabled:' => 'プラグインを有効にする場合はチェックを入れてください。',
'Hint cmd:' => 'コマンドラインの絶対パスを設定してください。',
# menu
'cmd exec' => 'コマンドを実行する',
# view
'Cmd Run' => 'コマンド実行',
);
1;
CMS.pm内容
package CMDEXEC::CMS;
use strict;
sub plugin {
return MT->component('CMDEXEC');
}
sub get_config {
my $plugin = plugin();
my ($key, $blog_id) = @_;
die "blog id non." unless $blog_id;
my $scope = $blog_id ? 'blog:'.$blog_id : 'system';
my %plugin_param;
$plugin->load_config(\%plugin_param, $scope);
my $value = $plugin_param{$key};
$value;
}
sub menu_permission {
my ($plugin) = @_;
my $blog = MT->instance->blog;
my $plugin_status = get_config("cmd_enabled",$blog->id);
return $plugin_status;
}
sub view {
my $app = shift;
my (%opt) = @_;
my $q = $app->{query};
my $blog_id = scalar $q->param('blog_id');
my $tmpl = $app->load_tmpl('view.tmpl');
return $app->build_page($tmpl);
}
sub do_run {
my $app = shift;
$app->validate_magic() or return;
my $q = $app->param;
my $result = runcmd($app);
my $param = {};
$param->{result} = $result;
my $tmpl = $app->load_tmpl('view.tmpl');
return $app->build_page($tmpl, $param);
}
sub runcmd {
use MT::Log;
my ($app) = @_;
my $q = $app->param;
my $blog_id = $q->param('blog_id');
my $cmdline = get_config('cmdline', $blog_id);
die unless $cmdline;
my $log_save = get_config('log_save', $blog_id);
my $system_cmd;
$system_cmd = $cmdline;
my $sys_result = `$system_cmd 2>&1`;
if($log_save) {
my $log = MT::Log->new;
$log->blog_id($blog_id);
$log->author_id($app->user->id);
$log->message($system_cmd . " " . $sys_result);
$log->save or die $log->errstr;
}
return $sys_result;
}
1;
config_template.tmplの内容
<mtapp:setting id="cmd_enabled" label="<__trans phrase="cmd enabled:">" hint="<__trans phrase="Hint enabled:">" show_hint="1">
<input type="checkbox" name="cmd_enabled" id="cmd_enabled" value="1" <mt:if name="cmd_enabled">checked="checked"</mt:if> class="cb" />
</mtapp:setting>
<mtapp:setting id="Run cmd" label="<__trans phrase="Run cmd:">" hint="<__trans phrase="Hint cmd:">" show_hint="1">
<input type="text" name="cmdline" id="cmdline" value="<mt:var name="cmdline" escape="html">" size="60" />
</mtapp:setting>
<mtapp:setting id="log_save" label="<__trans phrase="Log Save:">" hint="<__trans phrase="Log Save:">" show_hint="1">
<input type="checkbox" name="log_save" id="log_save" value="1" <mt:if name="log_save">checked="checked"</mt:if> class="cb" />
</mtapp:setting>
view.tmplの内容
<MTVersion setvar="mtversion">
<mt:setvarblock name="page_title"><__trans phrase="Cmd Run"></mt:setvarblock>
<mt:setvar name="position_actions_bottom" value="1" />
<mt:setvar name="lftp" value="1">
<mt:if name="mtversion" lt="7">
<mt:include name="include/header.tmpl" id="header_include">
</mt:if>
<mt:setvarblock name="page_content">
<div id="panel">
<form method="post" action="<mt:var name="script_url">" target="_blank">
<input type="hidden" name="__mode" value="cmd_run" />
<input type="hidden" name="magic_token" value="<mt:var name="magic_token">" />
<mt:if name="blog_id">
<input type="hidden" id="blog_id" name="blog_id" value="<mt:var name="blog_id">" />
</mt:if>
<mt:setvarblock name="action_buttons">
<button
type="submit"
accesskey="b"
title="<__trans phrase="Cmd Run">"
class="action primary-button"
><__trans phrase="Cmd Run"></button>
</mt:setvarblock>
<mt:include name="include/actions_bar.tmpl" bar_position="bottom" hide_pager="1" settings_bar="1">
</form>
<br>
<p><__trans phrase="Result"></p>
<textarea rows="50" cols="150"><mt:var name="result"></textarea>
</div>
</mt:setvarblock>
<mt:if name="mtversion" lt="7">
<mt:var name="page_content">
</mt:if>
<mt:if name="mtversion" lt="7">
<mt:include name="include/footer.tmpl">
</mt:if>
<mt:if name="mtversion" ge="7">
<mt:include name="layout/default.tmpl">
<mt:var name="layout">
</mt:if>
説明
プラグイン側の設定で。プラグインを利用するにチェックしないと動作しません。
ログも出力していますが、ファイル件数がおおいとログがみずらいので設定で、解除できるように
その他、コマンドも設定できます。注意、セキュリティ的に問題があれば、プログラム固定にしてください。$cmdlineを直接記入
最後に
個別転送とか、スケジュールまでは.......
コードを利用する方は、きちんと把握して、使ってくださいね。。必要ファイルまで消えちゃいますよ・・
2重起動とかチェックしていないのでやさしくクリックしてください。
author_nameとか。変えても問題ないです。。サポートしていませんから。。
では・・
追記
PowersyncのMovable Type 7版が出てました。・・