Perl5.38.2のインストール
Linux環境にPerl5.38.2をインストールしてみました。
ディストリビューションはCentOS8.1です。
1.ソースのダウンロード
ソースからビルドするので、「Perl Source」のページから「perl-5.38.2.tar.gz」をクリックしてダウンロードします。
2.ビルド
ダウンロードしたアーカイブを解凍して、ディレクトリに移動します。
# tar xvf perl-5.38.2.tar.gz
# cd perl-5.38.2
configureは次のオプションを追加しています。
# sh Configure -des -Dusethreads -Dinc_version_list=none
各オプションの意味は次の通りです。
- sh Configure:Configureをシェルで実行します。Configureはシステムに適したビルド設定を行うためのものです。
- -d:デフォルトの設定を使用することを指示します。ユーザーからの入力を求めずに進行します。
- -e:全ての設定を自動的に進めることを意味します。このオプションによりユーザーは一切の質問に対して「yes」と回答したことになります。
- -s:Silentモードを意味します。通常の動作では進行状況が表示されますが、-sを使用すると出力が抑制されます。
- -Dusethreads:Perlをスレッドサポート付きでビルドすることを指示します。これによりPerlでマルチスレッドプログラミングが可能になります。
- -Dinc_version_list=none:Perlインタープリタが特定のバージョンディレクトリを探さないように設定します。このオプションは、異なるバージョンのPerlモジュールが混在するのを防ぐために使われます。
下記のように実行されます。少し時間がかかります。
# sh Configure -des -Dusethreads -Dinc_version_list=none
First let's make sure your kit is complete. Checking...
Locating common programs...
:
If you compile perl5 on a different machine or from a different object
directory, copy the Policy.sh file from this object directory to the
new one before you run Configure -- this will help you with most of
the policy defaults.
#
完了したら、makeを実行します。これもかなり時間がかかります。
# make
# make test
# make install
パスはまだ古いバージョン(5.26.3)のままです。
# perl -v
This is perl 5, version 26, subversion 3 (v5.26.3) built for x86_64-linux-thread-multi
(with 51 registered patches, see perl -V for more detail)
今回インストールしたPerlは、/usr/local/binにインストールされたようです。
# which perl
/usr/local/bin/perl
# /usr/local/bin/perl -v
This is perl 5, version 38, subversion 2 (v5.38.2) built for x86_64-linux-thread-multi
シンボリックリンクを使って、perlのパスを新しいバージョンのものに書き換えます。古いバージョンのperlはリネームしてバックアップしておきます。
# cd /usr/bin
# ls -l perl
-rwxr-xr-x. 2 root root 14328 5月 12 2019 perl
# mv perl perl-5.26.3
# ln -s /usr/local/bin/perl perl
# ls -l perl
lrwxrwxrwx 1 root root 19 6月 13 22:30 perl -> /usr/local/bin/perl
最後にバージョン確認して、5.38.2になっていればOKです。
# perl -v
This is perl 5, version 38, subversion 2 (v5.38.2) built for x86_64-linux-thread-multi
3.参考サイト
参考サイトは下記です。ありがとうございました。
Movable Typeのブロックエディタ(MTBlockEditor)のカスタムブロックについて
Movable Typeのブロックエディタ(MTBlockEditor)のカスタムブロックの紹介です。
1.はじめに
Movable Type 8からMTBlockEditorがデフォルトのプラグインとなりました。
MTBlockEditorではデフォルトで用意されているブロックの他に、任意のブロック(カスタムブロック)を作成することができます。
ここでは、公式マニュアルに掲載されている「Markdown」ブロックを作ってみたいと思います。
参考:カスタムブロック機能を利用して高機能な Markdown を利用する
2.カスタムブロック(Markdown)の作成
左メニューより「ブロックエディタ」→「カスタムブロック」をクリック。
「新規作成」をクリック。
- 名前:Markdown
- 識別子:markdown
を設定。アイコンは設定しなくて大丈夫です。
「ブロック」の「+ブロックを追加」をクリック。
「テキスト(複数行)」をクリック。
- クラス名:source
- ブロック要素:P
- フォーマット:なし
を設定または選択。「ラベル」「説明」「規定値」は設定不要です。
「カスタムスクリプト」に下記の内容を設定。これがMarkdown記法に対応するためのスクリプトになります。
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/1.1.0/marked.min.js" integrity="sha256-POA+Q3FC8tyo/jZhQrw40H5mKcWAABdxNeUQ/uhIm4U=" crossorigin="anonymous"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
if (document.body.dataset.hasCompiledHtml) {
return;
}
const source = document.querySelector(".source").innerHTML;
MTBlockEditorSetCompiledHtml(marked(source));
});
</script>
「コンテナ要素で包む」の「編集した内容をDIV要素で囲む」と「ブロックの追加と削除」の「ブロックの追加と削除を許可する」のチェックを外します。「ブロックの追加と削除を許可する」のチェック有無の違いは3項で説明します。
「プレビューの表示」の「プレビューを表示する」はチェックします。チェックすることで、テキストエリアからフォーカスが外れると、プレビュー表示に切り替わりので分かりやすいと思います。
「保存」をクリックして作成完了です。
3.カスタムブロック(Markdown)の利用
ここではコンテンツデータの「テキスト(複数行)」から利用します。
「フォーマット」から「ブロックエディタ」を選択。
「+ブロックを追加」をクリック。
「Markdown」を選択(「名前」で設定した「Markdown」が表示されます)。
ここに表示されたアイコンは下記のSVGで生成されているようです。
data:image/svg xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'><style>text{font-family:'Arial';font-weight:bold;font-size:405px}</style><circle r='256' cx='256' cy='256' stroke='none' fill='#666'></circle><text x='256' y='274' text-anchor = 'middle' dominant-baseline = 'central' fill='white'>M</text></svg>
Markdown用のテキストエリアが表示されます。テキストエリアにフォーカスがあたったとき、「名前」で設定した「Markdown」がヘッダに表示されます。
設定画面で、「ブロックの追加と削除を許可する」のチェックを入れると、次のようにMarkdownブロック内に他のブロックが追加可能になります。
Markdown記法で入力してみます。「*~*」がイタリック、「**~**」が太字、「***~***」がイタリック+太字です。
フォーカスが外れると、プレビューが表示されます。
設定画面の「プレビューを表示する」のチェックを外せば、フォーカスが外れてもMarkdown記法がそのまま表示されます。
サイトの不具合について
2024年5月22日からページにアクセスすると、他のページに誘導される事象が発生しました。
切り分けのため、2024年5月23日の19時頃にサイトのすべての情報を削除しましたが事象が改善せず、24日にレンタルサーバ会社に問い合わせ、原因が判明したのがその日の昼頃。
24日の午後から手作業でデータを少しずつ復元させ、現在はほぼ通常運用に戻っています。
備忘録で状況を残しておきます。
1.事象の詳細
最初に気づいたのは、トップページ(index.php)の内容が書き換えられる事象でした。
その後、.htaccessが自動生成され、いくつかのページがトップページに誘導される内容が記載されていました。
そこからさらに(トップページに埋め込まれた、暗号化されたスクリプトで)別のページにリダイレクトされていました。
それらのファイルを削除したり、再構築で上書きしても、すぐに元の内容に書き換えられてしまいます。
topコマンドやpsコマンドでプロセスを確認しても怪しいプロセスはありません。
www配下のすべてのページをバックアップ後、削除しましたが、index.phpや.htaccessが自動生成される事象が解消ぜず、rootユーザーで実行されていると推測し、レンタルサーバ会社のサポートにチャットで問い合わせ。
借りているレンタルサーバのプランには、rootに昇格する権限はありませんでした。
上記の状況を伝えたところ、rootで不審なプロセスが動作していたようで、プロセスを削除して頂き、ようやく事象が解消しました。
その後、MTを新規インストールしてブログの再構築を実施し、画像等のアセットはバックアップデータから丸ごと復元せず、ひとつずつ確認しながら戻しています。
2.原因と対処
おそらく、契約しているアカウントのログインパスワードを破られた後、rootのパスワードも破られて該当のプロセスが仕掛けられたものと思われます。
サポートから「現在動作プロセスが残っております」と言われたのですが、こちらで確認できる範囲のプロセスに該当するものがないことを伝えたところ、サポート側でプロセスを削除して頂けました。
3.今後の対応
サーバログインパスワードはかなり強固なものを設定していましたが、今後は定期的に変更したいと思います。
Movable Typeのダッシュボードプラグインの作り方
Movable Typeのダッシュボードプラグインの作り方を紹介します。
1.はじめに
ダッシュボードプラグインを作る機会があったので、サンプルを使って作り方をまとめてみました。
ここでは下記のサンプルを紹介します。
ユーザーダッシュボードに「サンプルダッシュボードウィジェット」を表示します。
選択すると、下記のようにログインしたユーザー名を表示します。
×印をクリックすると、ウィジェットが削除されます。
このサンプルプラグインの構造は次の通りです。
DashboardSample
├ config.yaml
├ lib
│ └ DashboardSample
│ └ CMS.pm
└ tmpl
└ sample.tmpl
サンプルは下記のURLよりダウンロードできます。
以下、それぞれのファイルについて解説します。
2.config.yaml
下記にサンプルを示します。
name: DashboardSample
id: DashboardSample
widgets:
DashboardSample:
label: サンプルダッシュボードウィジェット
# plugin: $DashboardSample
template: sample.tmpl
order: 1000
singular: 1
set: main
handler: $DashboardSample::DashboardSample::CMS::test
view:
- user
主な項目の意味は次の通りです。
- template:ダッシュボード用テンプレートファイル名
- order:表示順序
- singular:単独表示("1"固定。プルダウンから選択・表示したあと、プルダウンの候補から外すためのもの)
- set:表示領域(main:中央/sidebar:右カラム)
- handler:ダッシュボード表示用ハンドラ名
- view:表示種別(user:ユーザーダッシュボード/system:システム管理画面/website:親サイト/blog:子サイト)
"plugin"という項目もありますが、記述無しでも動作するようなのでコメントアウトしています。
記述する場合は、サンプルのように「id:」の値を"$"つきで記述してください。
3.sample.tmpl
下記にサンプルを示します。
<mtapp:widget
id="DashboardSample"
class="widget DashboardSample"
label="サンプルダッシュボードウィジェット"
can_close="1">
<p><mt:var name="name"></p>
</mtapp:widget>
ここではパラメータ「name」の値だけを表示するようにしています。
<p><mt:var name="name"></p>
ダッシュボードを表示したあとに×印で削除できるようにするには、mtapp:widgetタグに「can_close="1"」を付与します。
4.CMS.pm
下記にサンプルを示します。
package DashboardSample::CMS;
use strict;
use warnings;
sub test {
my $app = shift;
my ( $tmpl, $param ) = @_;
my $user = $app->user;
}
1;
sample.tmplの"name"に値を渡すために、下記の1行を追加しています。
$param->{name} = $user->nickname;
Movable Type検索結果画面のMTIncludeタグでファイルを読み込む方法
Movable Type検索結果画面のMTIncludeタグでファイルを読み込む方法を紹介します。
1.はじめに
MTで再構築するファイルの拡張子を".php"にして、そのページの中で頻繁に更新される部分を、
<?php include('foo.html'); ?>
で読み込むことで、ページ全体の再構築不要で情報を更新することができます。
ただ、検索結果ページはPerlのCGIで動作するため、PHPの方法を利用することができません。
ということで、検索結果画面のMTIncludeタグでファイルを読み込む方法を紹介します。
2.検索結果画面のMTIncludeタグでファイルを読み込む
1項のfoo.phpのパスを、仮に「/var/www/html/foo.html」とします。
このファイルを検索結果画面のMTIncludeタグで読み込むには、下記の手順が必要です。
まず、mt-config.cgiに
AllowFileInclude 1
を設定します(注:4項参照)。
次に、ファイル読み込み部分を次のようにします。
<$mt:Include file="/var/www/html/foo.html"$>
これで、検索結果画面でも情報を更新する部品を利用することができます。
3.サイトパスにテンプレートタグを使用する
2項ではファイルパスに「/var/www/html」を直接記述しましたが、テンプレートタグでサイトパスを取得するには次のように記述します。
<mt:Setvarblock name="foo"><$mt:SitePath$>/foo.html</mt:setvarblock>
<$mt:Include file="$foo"$>
1行目のMTSetVarBlockタグで、サイトパスとファイル名を文字列結合したものを、変数fooに設定します。
2行目のMTIncludeタグで、fileモディファイアに「$foo」と書くことで、変数fooの内容が展開され、
<$mt:Include file="/var/www/html/foo.html"$>
と同じ結果となります。
4.注意事項
AllowFileIncludeはセキュリティ対策として、デフォルトで無効(=0)となっています。
理由は「テンプレート編集の権限だけをもつユーザーが、ファイルシステム上の任意のファイルを読み出せるのは問題であるため」のようです。
このカスタマイズを利用する場合は、上記のセキュリティに十分配慮してください。
ansibleのcopyモジュールでディレクトリを生成する方法
ansibleのcopyモジュールでディレクトリを生成する方法を紹介します。
1.問題点
ansibleのcopyモジュールでファイルをコピーしたいのですが、コピー先のディレクトリがなく、エラーになります。
試したのは下記の2種類です。
test.yml
---
- name: テスト
copy:
src: /tmp/hoge.txt
dest: /tmp/aaa/bbb/hoge.txt2
remote_src: yes
または
---
- name: テスト
copy:
src: /tmp/hoge.txt
dest: /tmp/aaa/bbb
remote_src: yes
これを実行すると、下記のように"Destination directory /tmp/aaa/bbb does not exist"というエラーになります。
$ ansible-playbook -i inventory test.yml
PLAY [act] ***************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************
ok: [server]
TASK [test : test.ymlをインクルード] *************************************************************************************************************
included: /var/tmp/ansible/roles/test/tasks/test.yml for server
TASK [test : テスト] *****************************************************************************************************************************
fatal: [server]: FAILED! => {"changed": false, "msg": "Destination directory /tmp/aaa/bbb does not exist"}
TASK [test : エラーが発生したため停止] ***********************************************************************************************************
fatal: [server]: FAILED! => {"changed": false, "msg": "ロール実行中にエラー発生"}
PLAY RECAP ***************************************************************************************************************************************
server : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=1 ignored=0
ということで、ansibleのcopyモジュールでディレクトリを生成する方法を紹介します。
2.ansibleのcopyモジュールでディレクトリを生成する
ansibleのcopyモジュールでディレクトリを生成するには、destオプションを"/"で終わらせます。
---
- name: テスト
copy:
src: /tmp/hoge.txt
dest: /tmp/aaa/bbb/
remote_src: yes
このansibleを実行すると正常にディレクトリを生成してくれます。
$ ansible-playbook -i inventory test.yml
PLAY [act] ***************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************
ok: [server]
TASK [test : test.ymlをインクルード] *************************************************************************************************************
included: /var/tmp/ansible/roles/test/tasks/test.yml for server
TASK [test : テスト] *****************************************************************************************************************************
changed: [server]
PLAY RECAP ***************************************************************************************************************************************
server : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
jQuery+ajaxでモーダルのコンテンツを取得する方法
jQuery+ajaxでモーダルのコンテンツを取得する方法を紹介します。
1.はじめに
モーダル表示の使い方は、たとえば商品ページで、その商品の詳細画像を表示するといったことが多いと思います。
その場合、HTMLページ内にすべてのモーダル用コンテンツを配置して、そこから取得・表示する実装になると思います。
ですが、ページ内にモーダル用のコンテンツをすべて記述すると、場合によってはページのサイズが大きくなり、ロード時間に影響します。
また商品ページではなく、たとえばモーダルをブログの記事ページとして表示させたい場合、上記の方法では大量のコンテンツをページ内に書き出す必要がありますが、現実的ではありません。
ということで、本記事ではモーダル用コンテンツをjQuery+ajaxで取得し、さらの前後リンクのコンテンツもjQuery+ajaxで取得する方法を紹介します。
2.サンプル
下記のリンクをクリックするとサンプルページに遷移します。
テキスト途中にある「ひらく」をクリックするとモーダルが表示され、前後リンクをクリックするとコンテンツをajaxで読み出して表示を切り替えます。
「あああ」のテキストを大量に挿入しているのは、モーダル表示後にスクロールしてもモーダルが移動しないことを示すためのものです。
サンプルはモーダルコンテンツの取得と前後リンクだけに着目しているので、CSSは最小限です。またアニメーションや「閉じる」ボタンの実装もありません。
以下、ソースとjQueryの解説です。
3.ソース
<meta charset="UTF-8" />
<style>
#modal {
display: block;
position: fixed;
opacity: 1;
z-index: 11000;
left: 45%;
margin-left: -77px;
top: 100px;
}
#modal_content {
border: 1px solid #000000;
padding: 30px;
}
#left {
position: absolute;
top: 100px;
left: -170px;
}
#right {
position: absolute;
top: 100px;
right: -170px;
}
</style>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script>
$(function(){
$(".open_modal").on('click', function(){
var url = $(this).attr('data-url');
$.ajax({
type: "POST",
url: url,
dataType: "html"
}).done(function(data) {
let main = $($.parseHTML(data)).filter('#main').html();
let prev = $($.parseHTML(data)).filter('#previous').text();
let next = $($.parseHTML(data)).filter('#next').text();
$('#modal_content').html(main);
if ( prev ) {
$('#left').attr('data-url', prev);
$('#left').css('display', 'block');
} else {
$('#left').css('display', 'none');
}
if ( next ) {
$('#right').attr('data-url', next);
$('#right').css('display', 'block');
} else {
$('#right').css('display', 'none');
}
$('#modal').css('display', 'block');
});
});
});
</script>
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<div class="open_modal" data-url="https://www.koikikukan.com/samples/20240313/test1.html">ひらく</div>
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<p>あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<br />あああ<b
r />あああ</p>
<div id="modal" style="display:none;">
<div class="open_modal" id="left" data-url=""><</div>
<div class="open_modal" id="right" data-url="">></div>
<div id="modal_content"></div>
</div>
4.解説
「ひらく」のclass属性"open_modal"をclickイベントで待ち合わせます。
<div class="open_modal" data-url="https://www.koikikukan.com/samples/20240313/test1.html">ひらく</div>
:
<script>
$(function(){
$(".open_modal").on('click', function(){
クリックされると要素内のdata-url属性値に設定したURLをattrメソッドで取得します。
var url = $(this).attr('data-url');
data-urlの値は下記のdata()でも取得できますが、この方法ではDOMのキャッシュが誤って取得されてしまうため、この記事の執筆時点ではdata()は絶対に使わないでください(この事象で2日ほど悩みました)。
var url = $(this).data('url');
取得したURLでコンテンツをajaxで取得します。
$.ajax({
type: "POST",
url: url,
dataType: "html"
$.ajax以外に$getでも取得可能です。
なお非同期による取得ではキャッシュが取得されてしまうこともあるので、POSTメソッドを使用する、cacheオプションをfalseにする等の対処を行ってください。
取得したコンテンツをそのままHTMLに展開できないケースを考慮して、部分取得を行います。
ここではコンテンツ部分と前後リンク部分をparseHTML()とfilter()を使います。この方法がベストプラクティスと思われます。
}).done(function(data) {
let main = $($.parseHTML(data)).filter('#main').html();
let prev = $($.parseHTML(data)).filter('#previous').text();
let next = $($.parseHTML(data)).filter('#next').text();
取得したHTMLをモーダルに反映します。
$('#modal_content').html(main);
URLを前後リンクに反映させます。このときも前述と同様の理由でdata()ではなく、attr()を使用してください。リンクがない場合は非表示にしています。
if ( prev ) {
$('#left').attr('data-url', prev);
$('#left').css('display', 'block');
} else {
$('#left').css('display', 'none');
}
if ( next ) {
$('#right').attr('data-url', next);
$('#right').css('display', 'block');
} else {
$('#right').css('display', 'none');
}
すべての設定が終わったらdisplayプロパティを使ってモーダル全体を表示します。
$('#modal').css('display', 'block');
ansibleでフィンガープリントを表示させない方法
ansibleでフィンガープリントを表示させない方法を紹介します。
1.問題点
ansibleでログイン経験がないサーバにログインをすると、下記のような「フィンガープリント」が表示されます。
The authenticity of host '[127.0.0.1]:22 ([127.0.0.1]:22)' can't be established.
RSA key fingerprint is SHA256:1pOx1qnpCf9UfJQPVaMRfJV/6LZkHWQXljHwwYGlN1g.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
ansible実行時にフィンガープリントを表示させないのですが、方法がわかりません。
ということで、ansibleでフィンガープリントを表示させない方法を紹介します。
2.ansibleでフィンガープリントを表示させない
ansibleでフィンガープリントを表示させないようにするには、ansible.cfgに下記の設定を追加します。
[ssh_connection]
ssh_args = '-o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
オプションの意味は次の通りです。
- ControlMaster=auto:sshのセッションが存在するときにそのセッションを再利用する仕組み
- ControlPersist=60s:ControlMasterをバックグランドにまわしてくれる機能
- StrictHostKeyChecking=no:ホストの~/.ssh/known_hostsに存在しないときに確認なしに接続し、フィンガープリントは確認なしにknown_hostsに記録されます
- UserKnownHostsFile=/dev/null:ホストの~/.ssh/known_hostsを常に空(/dev/null)にすることで、サーバ交換等でフィンガープリントが変わったときにエラーとなってしまうのを回避します
FFmpegをWindowsにインストールする方法
FFmpegをWindowsにインストールする方法を紹介します。
1.はじめに
Windows端末で「ScreenToGif」という、デスクトップキャプチャで取得した動画をMP4で保存しようとしたら、「FFmpegのパスが通っていません」と警告が表示されました。
FFmpeg自体インストールした記憶がないので、本記事でFFmpegをWindowsにインストールする方法を紹介します。
ちなみに、FFmpegはオープンソースのマルチメディアフレームワークで、主にコマンドラインツールとして動作し、多くの音声・動画フォーマットに対応した、ストリームの保存や変換が可能です。
2.FFmpegのダウンロード
FFmpegのページにアクセスして「Download」をクリック。
Windowsのアイコンをクリック。
「Windows builds by BtbN」をクリック。
「ffmpeg-master-latest-win64-gpl.zip」をクリック。
ダウンロードしたアーカイブを展開し、ここでは
C:\Program Files (x86)\ffmpeg
となるように配置します。
2.パスを通す。
タスクバーの検索フィールドに「システムの詳細設定」を入力して、「システムの詳細設定の表示」をクリック。
「環境変数」をクリック。
「xxのユーザー環境変数」の「Path」を選択した状態で「編集」をクリック。
「新規」をクリック。
今回は下記のパスを追加して「OK」をクリック。
C:\Program Files (x86)\ffmpeg\bin
前の画面も「OK」をクリックして、すべて閉じます。
3.動作確認
コマンドプロンプトを開いて、下記のコマンドを実行。
ffmpeg -version
パスが正常に通っていれば、下記のメッセージが表示されます。
これでFFmpegのインストール完了です。
シェルスクリプトのexpectで応答メッセージを振り分ける方法
シェルスクリプトのexpectで確認メッセージを振り分ける方法を紹介します。
1.問題点
シェルスクリプトを使ってパスワード入力が必要なコマンド(scp)を実行するためにexpectを使っています(下記)。
#!/bin/bash
expect -c "
spawn scp /home/foo/abc.txt foo@172.16.5.10:/home/foo
expect \"Are you sure you want to continue connecting (yes/no)?\"
send \"yes\n\"
expect \"password:\"
send \"hoge\n\"
interact
"
ですが、確認メッセージが2パターンあり、それらを振り分ける方法がわかりません。
具体的には、
% scp /home/foo/abc.txt foo@172.16.5.10:/home/foo
というコマンドを実行すると、初回は、
Are you sure you want to continue connecting (yes/no)?
と聞かれて、そのあと
password:
を聞かれるのですが、2回目以降は、
password:
しか聞かれません。
ということで、シェルスクリプトのexpectで確認メッセージを振り分ける方法を紹介します。
2.シェルスクリプトのexpectで確認メッセージを振り分ける
確認メッセージを振り分けるには、次のように書き換えます。
#!/bin/bash
expect -c "
spawn scp /home/foo/abc.txt foo@172.16.5.10:/home/foo
expect {
\"Are you sure you want to continue connecting (yes/no)?\" {
send \"yes\n\"
expect \"password:\"
send \"hoge\n\"
} \"password:\" {
send \"hoge\n\"
}
}
interact
"
具体的には、expect節で全体を括り、その中にifのthen節とelse節のように確認メッセージを分けて記述します。
Adobe Acrobat Reader(Adobe Reader)で電子印鑑を押印する方法
Adobe Acrobat Reader(Adobe Reader)で電子印鑑を押印する方法を紹介します。
1.電子印鑑の用意
電子印鑑は有料・無料など色々なサイトで作ることができます。
ここでは、画像の印鑑データを透過したり、テキスト打ち込みで印鑑が作れる「印鑑透過」で作ったものを利用します。
「STORES」というサイトでも無料ダウンロードできるようです。
2.PDFに電子印鑑を押印する
印鑑を押印したいPDFファイルを開き、「すべてのツール」タブの「入力と署名」または「電子サイン」をクリック。
「イニシャルを追加」をクリック。
「画像」をクリック。
電子印鑑にしたい画像を選択すると枠内に表示されるので「適用」をクリック(ここでサイズ等の調整はできません)。
なお、この印鑑を毎回使いたい場合は画面左下の「イニシャルを保存」をチェックしておくと便利です。ここではチェックした状態で進めます。
「適用」をクリックすると、PDFに適用した電子印鑑が表示され、マウスで移動できる状態になります。
位置を決めてクリックすると印鑑が固定されます。
印鑑に編集ボックスが表示されます。「A」は印鑑の拡大・縮小、ゴミ箱は印鑑の削除です。
その右の「…」は印鑑ではないイニシャル等におきかえるものです。
これでPDFを保存すれば、電子印鑑が捺印された状態になります。
次回以降は「電子サイン」に選択した印鑑が表示されるので、印鑑をクリックするだけでPDFに表示されます。×印をクリックすれば登録を解除できます。
ansibleのインベントリに設定した変数にアクセスする方法
ansibleのインベントリに設定した変数にアクセスする方法を紹介します。
1.問題点
ansibleで下記のインベントリを作成しました。
test00 ansible_host=192.168.0.10
test01 ansible_host=192.168.0.11
[all:vars]
ansible_user=test
ansible_ssh_pass=test
[server1]
test00
[server2]
test01
[server1:vars]
hoge=1
[server2:vars]
hoge=2
このインベントリでserver1ホスト指定で実行するときに、server2の変数hoge
[server2:vars]
hoge=2
の値を参照したいのですが、方法が分かりません。
ということで、ansibleのインベントリに設定した変数にアクセスする方法を紹介します。
2.ansibleのインベントリに設定した変数にアクセスする
ansibleのインベントリに設定した変数にアクセスするには、下記のように指定します。
hostvars[groups['server1'][0]]['hoge']
例:
- name: コマンド実行
command:
cmd: echo {{ hostvars[groups['server1'][0]]['hoge'] }}
register: result
- name: "結果出力"
debug:
msg: "{{ result.stdout_lines }}"
小粋空間プラグインのMovable Type8対応状況
小粋空間で販売させて頂いているプラグインのMovable Type8対応状況です。
Workflow
コンテンツデータ・記事・ウェブページで承認ワークフローを実現します。多段階承認やグループ別承認、複数承認も可能です。
すべてのグレードでMT8に対応しました。
CSVDataImExporter
CSV形式でMovable Typeのコンテンツデータ・記事・ウェブページデータのエクスポート・インポートが可能になるプラグインです。
通常版・機能拡張版、いずれもでMT8に対応しました。
SaveWithoutRebuild
Movable Typeでコンテンツデータや記事保存時に再構築を行わないためのプラグインです。
MT8に対応しました。
ListingFieldEditor
コンテンツデータや記事のカスタムフィールドのデータを一覧画面で編集できるプラグインです。
MT8に対応しました。
PowerListingFieldEditor
コンテンツデータや記事のカスタムフィールドのデータを一覧画面で一括編集できるプラグインです。
MT8に対応しました。
価格について
いずれも価格はMT7から据え置きですが、今後機能追加や機能差分等で改修を伴う場合は価格を変更させて頂くかもしれません。
その他
他のプラグインも随時、MT8に対応させて頂く予定です。
VirtualBoxにisoファイルをマウントしてローカルリポジトリでdnfを利用する方法
VirtualBoxにisoファイルをマウントしてローカルリポジトリでdnfを利用する方法を紹介します。
ここではWindowsマシンにVirtualBoxをインストールしてCentOSのゲストOSを作成し、Windowsのフォルダにisoファイルを配置している前提で進めます。
利用したいisoファイルは事前に入手し、Windowsの任意のフォルダにダウンロードしておいてください。
1.isoファイルのマウント
該当のゲストOSが停止・選択している状態で、VirtualBoxマネージャーの「設定」をクリック。
「ストレージ」をクリック。
「コントローラーIDE」にisoファイルを設定します。この例ではすでに設定してしまっているので、すいませんが他の記事を参考に設定してください。
また、このサンプルではCentOSのisoのみを設定していますが、デフォルトではVBoxGuestAdditions.isoがマウントされている可能性があります。その状態で後続のマウントを実施すると期待する結果にならないようなので、マウントしたいisoのみにしてください。
そしてゲストOSを起動して、/media配下にcdromディレクトリを作成し、mountコマンドを実行します。
# cd /media
# mkdir cdrom
# mount /dev/cdrom /media/cdrom
mount: /media/cdrom: 警告: デバイスは書き込み禁止です、読み込み専用でマウントします.
これで/media/cdrom配下が下記の状態になればOKです。
# pwd
/media/cdrom
# ls
AppStream BaseOS EFI TRANS.TBL images isolinux media.repo
2.リポジトリの設定変更
デフォルトでは外部のリポジトリを参照する設定になっているので、それらを変更します。
ちなみに、何も設定していない状態でdnf listを実行すると、次のようなエラーになります。
# dnf repolist
CentOS-8 - AppStream 6.8 B/s | 38 B 00:05
repo 'AppStream' のメタデータのダウンロードに失敗しました。
エラー: repo 'AppStream' のメタデータのダウンロードに失敗しました。
/etc/yum.repos.d/CentOS-AppStream.repoのenabledを1(有効)から0(無効)に変更します(★の行、以下同様)。
/etc/yum.repos.d/CentOS-AppStream.repo
:
[AppStream]
name=CentOS-$releasever - AppStream
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/AppStream/$basearch/os/
gpgcheck=1
enabled=0★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
/etc/yum.repos.d/CentOS-Base.repoのenabledを1(有効)から0(無効)に変更します。
/etc/yum.repos.d/CentOS-Base.repo
:
[BaseOS]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=BaseOS&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/BaseOS/$basearch/os/
gpgcheck=1
enabled=0★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
/etc/yum.repos.d/CentOS-Extras.repoのenabledを1(有効)から0(無効)に変更します。
/etc/yum.repos.d/CentOS-Extras.repo
:
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/extras/$basearch/os/
gpgcheck=1
enabled=0★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
/etc/yum.repos.d/CentOS-Media.repoのenabledを0(無効)から1(有効)に変更します。
/etc/yum.repos.d/CentOS-Media.repo
:
[c8-media-BaseOS]
name=CentOS-BaseOS-$releasever - Media
baseurl=file:///media/CentOS/BaseOS
file:///media/cdrom/BaseOS
file:///media/cdrecorder/BaseOS
gpgcheck=1
enabled=1★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
[c8-media-AppStream]
name=CentOS-AppStream-$releasever - Media
baseurl=file:///media/CentOS/AppStream
file:///media/cdrom/AppStream
file:///media/cdrecorder/AppStream
gpgcheck=1
enabled=1★
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
これで、dnfコマンドでローカルリポジトリが利用できるようです。
# dnf repolist
CentOS-BaseOS-8 - Media 154 MB/s | 2.2 MB 00:00
CentOS-AppStream-8 - Media 177 MB/s | 5.4 MB 00:00
repo id repo の名前 状態
c8-media-AppStream CentOS-AppStream-8 - Media 4,755
c8-media-BaseOS CentOS-BaseOS-8 - Media 1,659
MovableTypeプラグインの独自CGIをNginxに対応させる方法
Category:[トラブルシューティング]
Tag:[MovableType, Plugin, TroubleShooting, Workflow]
Permalink
MovableTypeプラグインの独自CGIをNginxに対応させる方法を紹介します。
これはMovable Type Advent Calendar 2023の24日目の記事です。
1.はじめに
以前、Workflowプラグインの独自CGI(mt-preview.cgi)がNginx環境に対応しておらず、アクセスすると「Not Found」というお客様からの申告があり、そのときの対処方法を備忘録で残しておきます。
MTプラグインで独自CGIを実装される方は、変更後または追加部分のみ参照されればよいかと思います。
冗長な修正があるかもしれませんが、実際に修正して回復した内容ということでそのまま掲載しておきます。
2.対処方法
まず。独自CGIの下記の1行を修正。
変更前
use MT::Bootstrap App => 'Workflow::App';
変更後
use MT::Bootstrap App => 'MT::App::Workflow';
config.yamlに"key"を追加。
key: Workflow
プラグインアプリケーション(独自CGI)の定義を丸々追加。ここでは、
- handler
- script
- cgi_path
の3項目を定義します。
applications:
workflow:
handler: MT::App::Workflow
script: '$Workflow::MT::App::Workflow::script_name'
cgi_path: >
sub {
my $path = MT->config->CGIPath;
$path =~ s!/$!!;
$path =~ s!^https?://[^/]*!!;
$path .= '/plugins/Workflow';
return $path;
}
エラーが発生した状態のCGI(Workflow.pm)はMT::App::CMSを継承していたのを、MT::Appを継承するように変更。
変更前
use base qw( MT::App::CMS );
変更後
use base qw( MT::App );
それに伴い、lib/Workflow/App.pm → lib/MT/App/Workflow.pm に移動。
移動したWorkflow.pm に、idとscript_nameを追加。
sub id {'workflow'}
sub script_name {'mt-preview.cgi'}
修正前はinit_requestしかなかったので、initを追加し、旧init_requestのadd_methodsをinitに移動。
変更前(抜粋)
sub init_request {
my $app = shift;
$app->SUPER::init_request(@_);
$app->add_methods( preview => \&preview );
$app->{ default_mode } = 'main';
$app->{ requires_login } = 0;
}
変更後(抜粋)
sub init {
my $app = shift;
$app->SUPER::init(@_);
$app->add_methods( preview => \&preview );
$app->{ default_mode } = 'main';
$app;
}
sub init_request {
my $app = shift;
$app->SUPER::init_request(@_);
$app->{requires_login} = 0;
}
これで独自CGIがNginxで動作するようになりました。