多段ssh接続が必要なサーバ上のファイルをvimで直接編集する方法

March 17,2020 11:55 PM
Category:[Linux]
Tag:[Linux, ssh]
Permalink

多段ssh接続が必要なサーバ上のファイルをvimで直接編集する方法を紹介します。

1.問題点

リモートサーバ上にファイル(test.txt)があります。

ここでは「SSHポートフォワーディング(トンネリング)とは」のウェブサーバ(10.10.10.123)上にあるものとします。

このファイルをクライアントサーバから編集する場合、

# ssh 10.10.10.10
# ssh 10.10.10.123
# vi test.txt

とします。

が、クライアントサーバからウェブサーバのファイルを直接編集する方法が分かりません。

ということで、多段ssh接続が必要なサーバ上のファイルをvimで直接編集する方法を紹介します。

2.多段ssh接続が必要なサーバ上のファイルをvimで直接編集する

多段ssh接続が必要なサーバ上のファイルをvimで直接編集するには、まず、1つめの画面でポートフォワーディングを実施します。

# ssh -N -L 10000:10.10.10.123:22 10.10.10.10

ここまでは通常のsshポートフォワーディングと同じです。なお、ポート番号はsshの「22」を指定しておきます。

そして、2つめの画面でvimを起動します。

# vim scp://root@localhost:10000//home/foo/test.txt

これで、多段ssh接続が必要なサーバ上のファイルのvim画面が開きます。

3.解説

vimは次のように指定することで、リモートサーバのファイルを編集することができます。

# vim scp://<ユーザ>@<リモートサーバのIPアドレス>//<編集対象ファイル>

今回は、この「リモートサーバのIPアドレス」にsshポートフォワーディング情報「localhost:10000」を与えます。

# vim scp://<ユーザ>@localhost:10000//<編集対象ファイル>

この設定により、多段ssh接続せずにvimの起動が行えます。

4.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

Linuxシェルでコマンド実行結果を入れた変数の改行を出力する方法

March 4,2020 11:55 PM
Category:[Linux]
Tag:[Linux]
Permalink

Linuxシェルでコマンド実行結果を入れた変数の改行を出力する方法を紹介します。

1.問題点

次のようなシェルスクリプト(test.sh)を作りました。

#!/bin/bash
 
result=`ls -l`
echo $result

このスクリプトを実行すると、

# ./test.sh
合計 16 -rw-r--r--. 1 root root 8 2月 13 17:40 2020 aaa -rw-r--r--. 1 root root 8 2月 13 17:40 2020 bbb -rw-r--r--. 1 root root 8 2月 13 17:40 2020 ccc -rwxrwxr-x. 1 root root 41 2月 13 17:38 2020 test.sh

となり、改行が失われますが、対処方法が分かりません。

ということで、シェルでコマンド実行結果を入れた変数の改行を出力する方法を紹介します。

2.コマンド実行結果を入れた変数の改行を出力する

コマンド実行結果を入れた変数の改行を出力するには、echoするときの変数をダブルクォーテーションで括ればOKです。

#!/bin/bash
 
result=`ls -l`
echo "$result"

これで改行が反映されます。

# ./test.sh
合計 16
-rw-r--r--. 1 root root  8  2月 13 17:40 2020 aaa
-rw-r--r--. 1 root root  8  2月 13 17:40 2020 bbb
-rw-r--r--. 1 root root  8  2月 13 17:40 2020 ccc
-rwxrwxr-x. 1 root root 41  2月 13 17:38 2020 test.sh
Comments [0] | Trackbacks [0]

cgroupsの利用方法

February 20,2020 11:55 PM
Category:[Linux]
Tag:[cgroups, Linux]
Permalink

cgroupsの利用方法を紹介します。

1.はじめに

cgroups(コントロールグループ)は、Linuxにおける、

  • CPUコア
  • CPU使用率
  • メモリ使用量
  • ディスクI/O
  • ネットワークI/O

などのプロセス資源を管理するためのサブシステムです。

ここではcpusetというサブシステムを利用して、

test1.sh
test2.sh

の2つのサンプルプログラムを、特定のCPUコアに割り当てる方法を紹介します。

なお、cgroupsが利用できるかどうかは、

# dmesg | grep cgroup
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Initializing cgroup subsys ns
Initializing cgroup subsys cpuacct
Initializing cgroup subsys memory
Initializing cgroup subsys devices
Initializing cgroup subsys freezer
Initializing cgroup subsys net_cls
Initializing cgroup subsys blkio
Initializing cgroup subsys perf_event
Initializing cgroup subsys net_prio

で確認できます。

上記の例では、

  • cpuset
  • cpu
  • ns
  • cpuacct
  • memory
  • devices
  • freezer
  • net_cls
  • blkio
  • perf_event
  • net_prio

のサブシステムが利用できます。

2.cgroupを使うための仮想ファイルシステムマウント

サブシステムのための仮想ファイルシステムをマウントします。

# mkdir /dev/cgroup
# mount -t cgroup -o cpuset cgroup /dev/cgroup

これで/dev/cgroup配下にcpusetというサブシステムが生成されます。

# cd /dev/cgroup
# ls -1
cgroup.event_control
cgroup.procs
cpuset.cpu_exclusive
cpuset.cpus
cpuset.mem_exclusive
cpuset.mem_hardwall
cpuset.memory_migrate
cpuset.memory_pressure
cpuset.memory_pressure_enabled
cpuset.memory_spread_page
cpuset.memory_spread_slab
cpuset.mems
cpuset.sched_load_balance
cpuset.sched_relax_domain_level
notify_on_release
release_agent
tasks

なお、デフォルトの設定では、ルートディレクトリに

/cgroups

があるようですが、コンフィグを利用して設定する回で解説するので今回は使用しません。

3.コントロールグループ作成

次にコントロールグループを作成します。

# cgcreate -g cpuset:/cpuset

これで

/dev/cgroup/cpuset

というコントロールグループが作成されます。

本当はcpuset配下にサブコントロールグループを作成したのですが、以降のコマンドでエラーになるため断念しました。

4.コントロールグループにCPU割り当て設定

CPU0を割り当てる設定を行います。

# cgset -r cpuset.mems=0 cpuset
# cgset -r cpuset.cpus=0 cpuset

これで、

/dev/cgroup/cpuset/cpuset.cpus

に"0"が設定されます。

cpuset.memsの設定を行わないと、次項のcgexecで

cgroup change of group failed

というエラーになります。

5.サンプルプログラムの実行(=CPUの割り当て)

前のメールではプログラム実行後にCPU割り当てを変更してますが
この方法であれば実行直後からCPU割り当てを変更できるようです。

# cgexec -g cpuset:/cpuset /root/test1.sh
# cgexec -g cpuset:/cpuset /root/test2.sh

この方法では、実際のcpコマンドも

# cgexec -g cpuset:/cpuset cp xxx xxx

のようになります。

6.top結果

このサーバではCPU0・CPU1の2コアがありますが、CPU0だけが使われていることが分かります。

top - 13:57:43 up 108 days,  7:03,  4 users,  load average: 2.00, 2.20, 2.19
Tasks: 157 total,   3 running, 154 sleeping,   0 stopped,   0 zombie
Cpu0  :100.0%us,  0.0%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu1  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   7510584k total,  3404032k used,  4106552k free,   326780k buffers
Swap:  3833848k total,        0k used,  3833848k free,  2333140k cached
Comments [0] | Trackbacks [0]

vimのコマンド一覧

February 18,2020 11:55 PM
Category:[Linux]
Tag:[Linux, vim]
Permalink

vimのコマンド一覧を作りました。

manコマンドを参考に、コマンドモードのコマンドを中心に網羅しています。

1.モードについて

manコマンドで定義されているvimのモードは、

  • コマンドモード
  • exモード
  • テキスト入力モード
  • ビジュアルモード

です。

「コマンドモード」はカーソルの移動やコピー、検索などvimを効率的に利用するためのメインとなるモードです。

「exモード」は、":"で始まり、置換などで利用します。

ところで、exモードとは何でしょうか。

そもそもviは、exというラインエディタをスクリーンエディタに拡張する形で作られたもので、viでexコマンドを使用するモードを「exモード」といいます。

「テキスト入力モード」は単純に文字を入力するためのモードです。

「ビジュアルモード」は矩形で処理を行うためのモードです。

manにはもうひとつ「オープンモード」が載っていますが、意味が不明なため、ここでは扱っていません。

2.コマンドモードの数字について

3項の表中にある「数字対応」は、コマンド実行前に任意の数字を入力すれば、入力数字分の挙動が行われることを指しています。

ネット上の情報で、コマンドの説明を数字と組み合わせたページはほぼなかったので、こういう機能があることをご存知の方は少ないかもしれません。

例えば、矢印キーでカーソルで移動する際、矢印キーの前に「30」などの数字を入力すれば、一気に30文字分カーソルを移動してくれます。

数字入力に慣れれば、編集作業をより効率的に行えるようになると思います。

3.コマンド一覧

モード変更
コマンド意味
iテキスト入力モードに変更(カーソル位置に文字を挿入)
Iテキスト入力モードに変更(行の先頭文字に文字を挿入)
aテキスト入力モードに変更(カーソル直後に文字を挿入)
Aテキスト入力モードに変更(カーソルの行末に文字を挿入)
oテキスト入力モードに変更(カーソルの下行に空行を挿入)
Oテキスト入力モードに変更(カーソル行に空行を挿入)
sテキスト入力モードに変更(カーソル位置をクリアして文字を挿入)
Sテキスト入力モードに変更(カーソル行をクリアして文字を挿入)
ESCコマンドモードに変更
:exモードに変更
Ctrl+vビジュアルモードに変更
カーソル移動(コマンドモード)
コマンド意味数字対応
←(またはh)左に1文字移動
→(またはl)右に1文字移動
↓(またはj)下に1行移動
↑(またはk)上に1行移動
-上に1行移動
+下に1行移動
改行下に1行移動
Ctrl+e1行前にスクロール
Ctrl+y1行後ろにスクロール
スペース右に1文字移動
Ctrl+f1ページ先へ
Ctrl+b1ページ前へ
Ctrl+d半ページ先へ
Ctrl+u半ページ前へ
H画面の一番上に移動
L画面の一番下bに移動
$行末に移動
0(ゼロ)行頭に移動
^カーソル行の空白除く先頭文字に移動
_カーソル行の空白除く先頭文字に移動
ggファイルの先頭に移動
Gファイルの末尾に移動
M画面中央の空白以外の先頭文字に移動
w次の単語に移動
m+1文字カーソルの位置をマーキング
'マーキング位置の行の先頭文字にジャンプ
`マーキング位置にジャンプ
編集(コマンドモード)
コマンド意味数字対応
xカーソル上の文字を1文字削除
Xカーソルの直前の文字を1文字削除
Dカーソル上の文字から行末まで削除
dwカーソル上の文字から空白までの文字を削除
dd行削除
yy行コピー
ywカーソル位置から次の空白までコピー
pカーソル行の下にペースト
ywの後であればカーソル行にペースト
Pカーソル行にペースト
.直前のコマンドを再実行
uアンドゥ
Uカーソル行の変更をすべてアンドゥ
Ctrl+rリドゥ
rカーソル上の文字を上書き
Rカーソル上以降の文字を上書き
Jカーソル行と次の行を連結
&直前の置換を繰り返し
~大文字小文字変換
検索(コマンドモード)
コマンド意味
/+検索文字後方検索
?+検索文字前方検索
n再検索(直前の検索と同方向)
N再検索(直前の検索と逆方向)
%カーソル上の文字に対応するペア文字
(カッコやブラケットなど)に移動
ファイル操作(コマンドモード)
コマンド意味
:w上書き保存
:w!強制上書き保存
:wq上書き保存と終了
:wq!強制上書き保存と終了
ZZ強制上書き保存と終了
:e再読み込み
:e!強制再読み込み
その他(コマンドモード)
コマンド意味
Ctrl+g情報表示(ファイル名,現在行など)
Ctrl+l画面のクリアと再描画
置換(exモード)
コマンド意味
:set number行番号表示
:set nonumber行番号非表示
:%s/文字列/置換文字列/g文字列を置換文字列に一括置換
Comments [0] | Trackbacks [0]

シェルスクリプトで動作するコマンドラインインタフェース

February 12,2020 11:55 PM
Category:[bash]
Tag:[bash, Linux]
Permalink

シェルスクリプトで動作するコマンドラインインタフェースを作りました。

1.はじめに

Linuxにログインしたターミナル上では、標準入力した文字列(コマンドライン)を編集することができます。また矢印キーでコマンド履歴を表示・編集することもできます。

が、シェルスクリプトを起動したあとの標準入力を、同じように編集したり、コマンド履歴を表示することはできません。

ネットを探しましたが同じようなものがみつかりませんでした。

ということで、シェルスクリプト上でコマンドラインを編集できるスクリプトを作ってみました。

このスクリプトでできるコマンドラインインタフェースは下記です。

  • Ctrl+a:カーソルを先頭に移動
  • Ctrl+b:カーソルを1文字左に移動
  • Ctrl+d:カーソル上の文字を削除
  • Ctrl+e:カーソルを末尾に移動
  • Ctrl+f:カーソルを1文字右に移動
  • Ctrl+k:カーソルより後方の文字を削除
  • Ctrl+u:カーソルより前方の文字を削除
  • Backspace:カーソルの左側の文字を削除
  • 上矢印:ヒストリ呼び出し
  • 下矢印:ヒストリ呼び出し
  • 左矢印:カーソルを1文字左に移動
  • 右矢印:カーソルを1文字右に移動
  • リターン:コマンド実行

スクリプトを任意の名称で保存して実行すると、スクリプトで定義したプロンプトを表示して標準入力待ちになります。

ご自身のスクリプトに合うよう、適当に組み込んでください。

不具合・改善等があれば適宜アップデートしていきます。

CentOS 7で動作確認しています。環境によっては期待通り動作しない可能性があります。予めご了承ください。

2.スクリプト

#!/bin/bash
 
# Copyright (c) 2020 www.koikikukan.com
 
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom
# the Software is furnished to do so, subject to the following
# conditions:
 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
 
history -r /root/.bash_history
 
# プロンプト
PROMPT="# "
 
PROMPT_LENGTH=${#PROMPT}
CURSOL_INIT_POS=$((PROMPT_LENGTH + 1))
COMMAND=''
LENGTH=0
COUNTER=0
POS=${CURSOL_INIT_POS}
 
function _history_update() {
    tput cub 1000
    tput dl 1
    COMMAND=`history | tail -$COUNTER | head -1 | sed -re "s/^\s+[0-9]+\s{2}//"`
    echo -n "${PROMPT}$COMMAND"
    LENGTH=${#COMMAND}
    POS=$((LENGTH + CURSOL_INIT_POS))
}
 
echo -n "${PROMPT}"
while IFS= read -r -n1 -s char; do
    case $char in
    $'\x1b')
        read -r -n2 -s rest
        char+="$rest"
        case $char in
        $'\033\x5b\x41')
            HISTORY_COUNT=`history|wc -l`
            if [ $COUNTER -le $HISTORY_COUNT ]; then
                COUNTER=$((COUNTER + 1))
                _history_update
            fi
        ;;
        $'\033\x5b\x42')
            if [ $COUNTER -gt 0 ]; then
                COUNTER=$((COUNTER - 1))
                _history_update
            fi
        ;;
        $'\033\x5b\x43')
            COMMAND_POS=$((LENGTH + PROMPT_LENGTH))
            if [ ${COMMAND_POS} -ge ${POS} ]; then
                tput cuf 1
                POS=$((POS + 1))
            fi
        ;;
        $'\033\x5b\x44')
            if [ ${POS} -gt ${CURSOL_INIT_POS} ]; then
                tput cub 1
                POS=$((POS - 1))
            fi
        ;;
    esac
    ;;
 
    $'\x08')
        if [ ${POS} -gt ${CURSOL_INIT_POS} ]; then
            LEFT_LENGTH=$((POS - CURSOL_INIT_POS))
            if [ ${LENGTH} -gt ${LEFT_LENGTH} ]; then
                TMP=$((LEFT_LENGTH - 1))
                COMMAND=`echo "${COMMAND}" | sed -e "s/^\(.\{${TMP}\}\).\(.*\)$/\1\2/"`
            else
                DEL=${COMMAND: -1}
                COMMAND="${COMMAND/%${DEL}/}"
            fi
            tput dl 1
            tput cub 1000
            echo -n "${PROMPT}${COMMAND}"
            if [ ${LENGTH} -gt ${LEFT_LENGTH} ]; then
                tput cub 1000
                POS2=$((POS - 2))
                tput cuf ${POS2}
            fi
            POS=$((POS - 1))
            LENGTH=$((LENGTH - 1))
        fi
    ;;
 
    $'\0a')
        history -s "${COMMAND}"
        echo
        if [ -n "$COMMAND" ];then
            eval "${COMMAND}"
        fi
        LENGTH=0
        COMMAND=''
        POS=$CURSOL_INIT_POS
        echo -n "${PROMPT}"
    ;;
 
    $'\ca')
        if [ ${POS} -gt ${CURSOL_INIT_POS} ]; then
            tput cub 1000
            tput cuf ${PROMPT_LENGTH}
            POS=$CURSOL_INIT_POS
        fi
    ;;
 
    $'\cb')
        if [ ${POS} -gt ${CURSOL_INIT_POS} ]; then
            tput cub 1
            POS=$((POS - 1))
        fi
    ;;
 
    $'\cd')
        TMP=$((LENGTH + PROMPT_LENGTH))
        if [ ${POS} -le ${TMP} ]; then
            LEFT_LENGTH=$((POS - CURSOL_INIT_POS))
            if [ ${POS} -ne ${CURSOL_INIT_POS} ]; then
                COMMAND=`echo "${COMMAND}" | sed -e "s/^\(.\{${LEFT_LENGTH}\}\).\(.*\)$/\1\2/"`
            else
                COMMAND="${COMMAND:1}"
            fi
            tput dl 1
            tput cub 1000
            echo -n "${PROMPT}${COMMAND}"
            if [ ${LENGTH} -gt ${LEFT_LENGTH} ]; then
                tput cub 1000
                POS2=$((POS - 1))
                tput cuf ${POS2}
            fi
            LENGTH=$((LENGTH - 1))
        fi
    ;;
 
    $'\ce')
        COMMAND_POS=$((LENGTH + PROMPT_LENGTH))
        if [ ${COMMAND_POS} -ge ${POS} ]; then
            tput cub 1000
            tput cuf $COMMAND_POS
            POS=$((COMMAND_POS+1))
        fi
    ;;
 
    $'\cf')
        COMMAND_POS=$((LENGTH + PROMPT_LENGTH))
        if [ ${COMMAND_POS} -ge ${POS} ]; then
            tput cuf 1
            POS=$((POS + 1))
        fi
    ;;
 
    $'\ck')
        LEFT_LENGTH=$((POS - CURSOL_INIT_POS))
        if [ ${LENGTH} -gt ${LEFT_LENGTH} ]; then
            COMMAND=`echo "${COMMAND}" | sed -e "s/^\(.\{${LEFT_LENGTH}\}\).*$/\1/"`
        else
            continue
        fi
        tput dl 1
        tput cub 1000
        echo -n "${PROMPT}${COMMAND}"
        LENGTH=$((POS - CURSOL_INIT_POS))
    ;;
 
    $'\cu')
        LEFT_LENGTH=$((POS - CURSOL_INIT_POS))
        RIGHT_LENGTH=$((LENGTH - LEFT_LENGTH))
        if [ ${POS} -gt ${CURSOL_INIT_POS} ]; then
            COMMAND=`echo "${COMMAND}" | sed -e "s/^.*\(.\{${RIGHT_LENGTH}\}\)$/\1/"`
        else
            continue
        fi
        tput dl 1
        tput cub 1000
        echo -n "${PROMPT}${COMMAND}"
        tput cub 1000
        tput cuf $PROMPT_LENGTH
        POS=$CURSOL_INIT_POS
        LENGTH=$((RIGHT_LENGTH))
    ;;
 
    *)
        LEFT_LENGTH=$((POS - CURSOL_INIT_POS))
        if [ ${LENGTH} -gt ${LEFT_LENGTH} ]; then
            COMMAND=`echo "${COMMAND}" | sed -e "s/^\(.\{${LEFT_LENGTH}\}\)/\1$char/"`
        else
            COMMAND="${COMMAND}$char"
        fi
        tput dl 1
        tput cub 1000
        echo -n "${PROMPT}${COMMAND}"
        if [ ${LENGTH} -gt ${LEFT_LENGTH} ]; then
            tput cub 1000
            tput cuf ${POS}
        fi
        POS=$((POS + 1))
        LENGTH=$((LENGTH + 1))
    ;;
    esac
done

3.ライセンス

本スクリプトはMITライセンスです。

Comments [0] | Trackbacks [0]

Excelの$の意味

February 6,2020 11:55 PM
Category:[Excel]
Tag:[Excel, Office]
Permalink

Excelの"$"の意味について調べてみました。

Excelの"$"は「絶対参照」を意味します。

例えば、次のような縦方向に日付を入れたスケジュール表があります。

縦方向に日付を入れたスケジュール表

今日の日付に色を付けたい場合、条件付き書式に

=($A2=TODAY())

を記載します(詳細は「Excelで今日の日付の列に色をつける方法」を参照)。

条件付き書式

逆に、横方向に日付を入れたスケジュール表があります。

横方向に日付を入れたスケジュール表

今日の日付に色を付けたい場合、条件付き書式に

=(B$1=TODAY())

と記載します。

条件付き書式

つまり、前者の"$A2"はセルの列を固定したい場合、後者の"B$1"は行を固定したい場合に使います。

行と列の両方を固定したい場合は、

$A$1

のように記述します。

たとえば、下記の例ではA1~A3の合計をA4セルに

=SUM(A1,A3)

で表示しています。

セルのコピー

このA4セルをB6セルにコピーすると、セルの式が、

=SUM(B3,B5)

に自動的に書き換えられ、B3~B5セルの合計を表示します。

セルのコピー

A4セルの結果をそのまま表示させたければ、A4セルの式を

=SUM($A$1,$A$3)

にします。

セルのコピー

これでB6セルにコピーしても、A4セルの値が保持されます。

セルのコピー

Comments [0] | Trackbacks [0]

Excelで今日の日付の列に色をつける方法

February 3,2020 11:55 PM
Category:[Excel]
Tag:[Excel, Office]
Permalink

Excelで今日の日付の列に色をつける方法を紹介します。

1.はじめに

下の図のようなスケジュール表を作りました。

(クリックで拡大)
スケジュール表

この表で、今日の日付の列の色を変えたいのですが、方法が分かりません。

ということで、Excelで今日の日付の列に色をつける方法を紹介します。

なお、A1セルの「2020年」はセルの形式をユーザー定義で「@"年"」、B1セルの「2月」はユーザー定義で「@"月"」にしているので、セルに設定されている実際の値は「2020」「2」です。

サンプルを作って動かしてみたい場合は、これらのセルに数値を入力してください。

また、日付の1~29は数値で設定しています。

参考までに、今日の日付の「行」に色をつける方法は「Excelで今日の日付に色をつける方法」で紹介しています。

2.今日の日付の列に色をつける

今日の日付の列に色をつける手順を説明します。

色を付けたい部分を選択状態にします。

(クリックで拡大)
色を付けたい部分を選択状態

「ホーム」タブ→「条件付き書式」→「新しいルール」をクリック。

新しいルール

「数式を使用して、書式設定するセルを選択」をクリック。

(クリックで拡大)
数式を使用して、書式設定するセルを選択

「次の数式を満たす場合に値を書式設定」のテキストフィールドに下記の内容を設定(内容は後で解説)。

=(DATEVALUE($A$1&"/"&$B$1&"/"&B$2)=TODAY())

次の数式を満たす場合に値を書式設定

右下の「書式」をクリック。

書式

変えたい色を選択して「OK」をクリック。ここでは緑を選択します。

(クリックで拡大)
変えたい色を選択

前の画面の「プレビュー」に選択した色が表示されたことを確認して「OK」をクリック。

プレビュー

これで今日の日付(2月3日)の列の色が変わります。

スケジュール表

3.解説

わかりやすくするため冒頭の表は一旦置いておき、次の簡素な表で仕組みを説明します。

スケジュール表

B1~F1セルの形式は「日付」です。

この表の場合、「次の数式を満たす場合に値を書式設定」のテキストフィールドに設定する数式は、

=(B$1=TODAY())

になります。

カッコ内の左辺は日付の開始セルを指定します。"$"は直後の値"1"を固定することを意味するので、

B1
C1
D1
E1
F1

の5つのセルが対象になります。

TODAY()は今日の日付を表示する関数です。

つまりこの式を設定することで、「B1~F1のセルの値が今日の日付と等しいこと」が色を変える条件になります。

仕組みがなんとなくお分かりになったと思うので、冒頭のサンプルの説明に戻ります。

(クリックで拡大)
スケジュール表

冒頭のサンプルは、さきほど紹介した簡素なサンプルとほぼ同じ条件を設定しています。

ただ、冒頭のサンプルは年月日がそれぞれ異なるセルに設定されているため、「年」「月」「日」の文字列を、それぞれのセルから取得して結合する処理が追加されています。

それが、

=(DATEVALUE($A$1&"/"&$B$1&"/"&B$2)=TODAY())

の左辺、

DATEVALUE($A$1&"/"&$B$1&"/"&B$2)

のカッコ内にある、

$A$1&"/"&$B$1&"/"&B$2

になります。

"&"は文字列結合の記号です。

この「年」「月」「日」文字列結合でのポイントは、セルの固定が必要な個所にすべて"$"を付与しています。

"$"がついていないのは、日付を表すセルの"B"だけで(赤色部分)、この部分が可変になります。

$A$1&"/"&$B$1&"/"&B$2

そして、"B"の直後の数字"2"は固定なので、これでB2~AD2のセルが対象になります。

DATEVALUE()は、文字列を日付に変換する関数です。

残りのTODAYなどは簡素なサンプルと同じです。

Comments [0] | Trackbacks [0]

Office(Woprd/Excel/PowerPoint)の貼り付けで「貼り付けオプション」を表示させない方法

February 2,2020 11:55 PM
Category:[office]
Tag:[Office]
Permalink

Office(Woprd/Excel/PowerPoint)の貼り付けで「貼り付けオプション」を表示させない方法を紹介します。

1.はじめに

Wordで適当な文字を入力します。

入力した文字を選択してコピーします。

ペーストすると、赤枠で囲んだ「貼り付けオプション」が表示されます。

この貼り付けオプションは貼り付け時に形式を選択するためのものですが、貼り付ける位置によっては他のテキストに被ってしまい、邪魔になるときがあります。

この「貼り付けオプション」を表示しないようにしたいのですが、方法が分かりません。

ということで、Office(Woprd/Excel/PowerPoint)の貼り付けで「貼り付けオプション」を表示させない方法を紹介します。

2.「貼り付けオプション」を表示させないようにする(方法1)

表示された「貼り付けオプション」を消すには、Escキーを押下します。

3.「貼り付けオプション」を表示させないようにする(方法2)

「貼り付けオプション」を常に表示させないようにするには、「ファイル」→「オプション」でオプション画面を表示し、「詳細」タブをクリックして、「コンテンツを貼り付けるときに[貼り付けオプション]ボタンを表示する」のチェックを外して、「OK」をクリック。

(クリックで拡大)

これで貼り付けたときに「貼り付けオプション」が表示されなくなります。

Comments [0] | Trackbacks [0]

PHPをビルドしてApacheと連携させる方法

January 14,2020 11:55 PM
Category:[Apache]
Tag:[Apache, php]
Permalink

PHPをビルドしてApacheと連携させる方法を紹介します。

1.はじめに

ブラウザからPHPファイルを読み込ませたいため、Linux(CentOS)のApache2.4にPHP5.xを組み込んでみました(Apacheはインストール済)。

# yum install php

インストール後、httpd.confに下記の2行を追記。

LoadModule php5_module /usr/lib64/httpd/modules/libphp5.so
 :
AddType application/x-httpd-php .php

が、Apacheを再起動したところ、下記のエラーが発生しました。

# cd /usr/local/apache2/bin
# ./apachectl restart
httpd: Syntax error on line 150 of /usr/local/apache2/conf/httpd.conf: Cannot load /usr/lib64/httpd/modules/libphp5.so into server: /usr/lib64/httpd/modules/libphp5.so: undefined symbol: unixd_config

追加したLoadModuleディレクティブでひっかかっているようです。

ネットで調べたところ、yumでインストールしたApache2.4とPHP5ではうまく連携できないようです。

Apache2.2に戻せば連携できるようですが、PHPをソースからビルドすれば連携させられることがわかったので、その方法で実施しました。

2.PHPをビルドしてApacheと連携させる

連携させるための仕組みをもう少し説明すると、PHPを手動でインストールする際、Apacheと連携させるためのモジュールlibphp5.soを、Apache2.4にバンドルされているapxsというものを利用して生成します。

yumでインストールしたPHPに含まれていたlibphp5.soは、Apache2.2対応のものだったのかもしれません。

yumでインストールしたPHPを削除

# yum remove php

yumでlibxml2とlibxml2-develをインストール。

# yum install -y libxml2 libxml2-devel

PHP5.x系の最終バージョンをダウンロード

wget http://jp2.php.net/get/php-5.6.40.tar.gz/from/this/mirror -O php-5.6.40.tar.gz

スタンドアローン環境の場合は、https://www.php.net/releases/からphp-5.6.40.tar.gzをダウンロードして、Linuxマシンに転送します。

tar.gzを展開します。

# tar xzf php-5.6.40.tar.gz

展開したディレクトリに移動。

# cd php-5.6.40

Apacheと連携させるためのlibphp5.soを作るために、./configure実行時にapxsを指定します。

# ./configure --with-apxs2=/usr/local/apache2/bin/apxs

これでhttpd.confに

LoadModule php5_module modules/libphp5.so

がビルド時に自動的に設定されます。

後は通常通りのビルドを実施します。

# make
# make test
# make install

ビルド後はApacheを再起動します。

# cd /usr/local/apache2/bin
# ./apachctl restart

/usr/local/apache2/htdocs配下に

<?php phpinfo(); ?>

の内容をindex.phpで作成し、ブラウザでアクセスしてPHPの情報が表示されればOKです。

3.参考

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

MovableTypeでプラグインの重複チェックができる「DuplicatePluginCheckerプラグイン」

January 7,2020 11:55 PM
Category:[プラグイン管理]
Tag:[DuplicatePluginChecker, MovableType, Plugin]
Permalink

MovableTypeでプラグインの重複チェックができる「DuplicatePluginCheckerプラグイン」を公開します。

1.機能

MTプラグインの重複配置は動作異常になる可能性があります」でご紹介したとおり、同じプラグイン名のプラグインがpluginsディレクトリに置かれていると、期待しない動作になります(どちらか一方のプラグインが優先されるのではなく、予想外の動作になる)。

本プラグインを利用すれば、pluginsディレクトリに同名のプラグインが配置されている場合、管理画面にアクセスした際、次のようなエラーを表示します。

(クリックで拡大)
エラー

2.プラグインのインストール

下記のリンクをクリックして、DuplicatePluginCheckerのプラグインアーカイブをダウンロードします。

DuplicatePluginChecker_0_01.zip

プラグインアーカイブを展開し、pluginsフォルダにあるDuplicatePluginCheckerフォルダをMovable Typeのアプリケーションディレクトリのpluginsディレクトリにアップロードします。

システム管理画面のプラグイン設定画面で「DuplicatePluginChecker~」が表示されればインストール完了です。

プラグイン設定画面

3.使い方

システム管理画面の「設定」→「プラグイン」を選択したとき、同名のプラグインが配置されていれば冒頭のようなエラーを表示します。

Comments [0] | Trackbacks [0]

MTプラグインの重複配置は動作異常になる可能性があります

December 24,2019 11:59 PM
Category:[プラグイン]
Tag:[MovableType]
Permalink

この記事は Movable Type Advent Calendar 2019 24日目の記事です。

MTプラグインの重複配置は動作異常になる可能性があります、というお話です。

1.はじめに

当方で開発しているMTプラグインを導入頂いたお客様から、「期待通りに動作しない」というご質問を、年に2~3回頂きます。

プラグインのバグもありますが、そうでない場合の原因として最も多いのが「古いバージョンの同じプラグインをpluginsディレクトリに置いている」です。

例えば、Workflowプラグインを購入されたお客様が、プラグインのバージョンアップで、前のバージョンのWorkflowプラグインのディレクトリ名を、"Workflo-backup"のようにリネームして、pluginsディレクトリに置いたままとします。

お客様は、リネームした古いプラグインは動作しないと思われているようですが、リネームしたプラグインは、バージョンアップしたプラグインとは別のプラグインとして登録されてしまいます。

同じ処理が2つ登録されてしまうと、perlとして正常に動作しなくなるようで、これが原因でお問い合わせがくるわけです。

結論から申し上げますと、プラグインのバージョンアップあるいは、プラグインの評価版から製品版に乗り換えられる際、前のプラグインはpluginsディレクトリから必ず削除または移動してください。

2.2つのプラグインが登録されてしまう仕組み

MTのプログラムをトレースして、2つのプラグインが登録されてしまう仕組みを説明します。

ブラウザからMTにアクセスするとinit()が起動します。

lib/MT.pm

sub init {
    my $mt    = shift;
    my %param = @_;
 
    $mt->bootstrap() unless $MT_DIR;
    $mt->{mt_dir}     = $MT_DIR;
    $mt->{config_dir} = $CFG_DIR;
    $mt->{app_dir}    = $APP_DIR;
 
    $mt->init_callbacks();
 
    ## Initialize the language to the default in case any errors occur in
    ## the rest of the initialization process.
    $mt->init_config( \%param ) or return;
    $mt->init_lang_defaults(@_) or return;
    require MT::Plugin;
    $mt->init_addons(@_) or return;
    $mt->init_config_from_db( \%param ) or return;
    $mt->init_debug_mode;
    $mt->init_plugins(@_) or return;★

★でinit_plugins()が起動されます。

sub init_plugins {
    my $mt = shift;
 
    # Load compatibility module for prior version
    # This should always be MT::Compat::v(MAJOR_RELEASE_VERSION - 1).
    if ( MT->config('RequiredCompatibility') < 4.0 ) {
        require MT::Compat::v3;
    }
 
    my $cfg          = $mt->config;
    my $use_plugins  = $cfg->UsePlugins;
    my @PluginPaths  = $cfg->PluginPath;
    my $PluginSwitch = $cfg->PluginSwitch || {};
    my $plugin_sigs  = join ',', sort keys %$PluginSwitch;
    $mt->_init_plugins_core( $PluginSwitch, $use_plugins, \@PluginPaths );★

★で_init_plugins_core()が起動されます。

    sub _init_plugins_core {
        my $mt = shift;
        my ( $PluginSwitch, $use_plugins, $PluginPaths ) = @_;
 
        my $timer;
        if ( $mt->config->PerformanceLogging ) {
            $timer = $mt->get_timer();
        }
 
        foreach my $PluginPath (@$PluginPaths) {
            my $plugin_lastdir = $PluginPath;
            $plugin_lastdir =~ s![\\/]$!!;
            $plugin_lastdir =~ s!^.*[\\/]!!;

if ( opendir my $DH, $PluginPath ) {
my @p = readdir $DH;★

ここが原因の根本(悪い意味ではなく実装上の仕様)ですが、★のreaddirで、指定されたプラグインパス(デフォルトはplugins)配下のディレクトリをすべて読み込みます。

先の例であれば、

$VAR1 = [ '.', '..', 'BlockEditor', 'Comments', 'FacebookCommenters', 'FormattedText', 'FormattedTextForTinyMCE', 'GoogleAnalytics', 'Markdown', 'OpenID', 'spamlookup', 'Textile', 'TinyMCE', 'Trackback', 'WidgetManager', 'Workflow', 'Workflow-backup', 'WXRImporter' ];

のように、'Workflow'と'Workflow-backup'の2つが含まれます。

このあとの処理で、yaml形式のプラグインであれば、

                closedir $DH;
                for my $plugin (@p) {
                    next if ( $plugin =~ /^\.\.?$/ || $plugin =~ /~$/ );
 
                    $plugin_full_path
                        = File::Spec->catfile( $PluginPath, $plugin );
                    if ( -f $plugin_full_path ) {
                        $plugin_envelope = $plugin_lastdir;
                        __load_plugin( $mt, $timer, $PluginSwitch,
                            $use_plugins, $plugin_full_path, $plugin )
                            if $plugin_full_path =~ /\.pl$/;
                        next;
                    }
 
                    my $plugin_dir = $plugin;
                    $plugin_envelope = "$plugin_lastdir/" . $plugin;
 
                    foreach my $lib (qw(lib extlib)) {
                        my $plib
                            = File::Spec->catdir( $plugin_full_path, $lib );
                        unshift @INC, $plib if -d $plib;
                    }
 
                    # handle config.yaml
                    my $yaml = File::Spec->catdir( $plugin_full_path,
                        'config.yaml' );
 
                    if ( -f $yaml ) {
                        __load_plugin_with_yaml( $use_plugins, $PluginSwitch,
                            $plugin_dir );★
                        next;
                    }

★で__load_plugin_with_yaml()が実行され、

    sub __load_plugin_with_yaml {
        my ( $use_plugins, $PluginSwitch, $plugin_dir ) = @_;
        my $pclass
            = $plugin_dir =~ m/\.pack$/
            ? 'MT::Component'
            : 'MT::Plugin';
 
        # Don't process disabled plugin config.yaml files.
        if ($pclass eq 'MT::Plugin'
            && (!$use_plugins
                || ( exists $PluginSwitch->{$plugin_dir}
                    && !$PluginSwitch->{$plugin_dir} )
            )
            )
        {
            $Plugins{$plugin_dir}{full_path} = $plugin_full_path;
            $Plugins{$plugin_dir}{enabled}   = 0;
            return;
        }
        return if exists $Plugins{$plugin_dir};
        my $id = lc $plugin_dir;
        $id =~ s/\.\w+$//;
        my $p = $pclass->new(
            {   id       => $id,
                path     => $plugin_full_path,
                envelope => $plugin_envelope
            }
        );
 
        # rebless? based on config?
        local $plugin_sig = $plugin_dir;
        $PluginSwitch->{$plugin_sig} = 1;
        MT->add_plugin($p);
        $p->init_callbacks();
    }

プラグインとして追加されてしまうようです(これ以降トレースしていないので認識誤りでしたらお許しを)。

なお、システム管理画面のプラグイン一覧には、リネームしたプラグインは新しいプラグインと(コンフィグの設定が)同じなので、2つ表示されることはありません。

ということで、旧プラグインはリネームではなく、別のディレクトリに移動しましょう。

この記事には続きがありますが、時間切れなのでこの辺で。

Comments [0] | Trackbacks [0]

Windows10のエクスプローラーでフォルダのツリーを展開する方法

December 16,2019 11:55 PM
Category:[Windows]
Tag:[Windows]
Permalink

Windows10のエクスプローラーでフォルダのツリーを展開する方法を紹介します。

1.問題点

Windows10のエクスプローラーは、デフォルト状態でフォルダのツリーが展開されません。

キャプチャのように「\test\test1\test1-1\test1-1-1」を選択しても左のツリーは展開されません。

(クリックで拡大)
フォルダオプション画面

手動で展開することは可能ですが面倒です。またネットワーク越しのフォルダは手動で展開できない場合があります。

ということで、Windows10のエクスプローラーでフォルダのツリーを展開する方法を紹介します。

2.Windows10のエクスプローラーでフォルダのツリーを展開する

Windows10のエクスプローラーでフォルダのツリーを展開するには、メニューバーの「表示」をクリック。

エクスプローラー

右側にある「オプション」のアイコン(文字ではない方)をクリック。

「オプション」のアイコン

フォルダオプション画面が開くので、「表示」タブの「開いているフォルダーまで展開」をチェックして「OK」をクリック。

フォルダオプション画面

これでフォルダツリーが自動で展開されます。

フォルダオプション画面

Comments [0] | Trackbacks [0]

PythonでJSONファイルの日本語キーを読む方法

November 14,2019 11:55 PM
Category:[Python]
Tag:[JSON, Python]
Permalink

PythonでJSONファイルの日本語キーを読む方法を紹介します。

1.問題点

次のJSONファイルがあります。文字コードはUTF-8です。

sample.json

{
"内容" : "工事",
"情報" : [
  {
  "番号" : "123",
  "名前" : "東京"
  },
  {
  "番号" : "456",
  "名前" : "大阪"
  } ]
}

このファイルを読み込み、"東京"というデータを表示するPythonスクリプト(sample.py)を作りました。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import sys
import json
 
# 引数取得
args = sys.argv
 
# JSONファイルオープン,パース
f = open(args[1], 'r')
data = json.load(f, 'utf-8')
f.close()
 
print json.dumps(data["情報"][0]["名前"], ensure_ascii=False)

が、実行すると次のようなKeyErrorになります。

# ./sample.py sample.json
Traceback (most recent call last):
  File "./sample.py", line 14, in 
    print json.dumps(data["情報"][0]["名前"], ensure_ascii=False)
KeyError: '\xe6\x83\x85\xe5\xa0\xb1'

ということで、PythonでJSONファイルの日本語キーを読む方法を紹介します。

2.日本語のキーを読む

PythonでJSONファイルの日本語キーを読むには、JSONを取得する際のキーに"u"を付与します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import sys
import json
 
args = sys.argv
 
# JSONファイルオープン,パース
f = open(args[1], 'r')
data = json.load(f, 'utf-8')
f.close()
 
print json.dumps(data[u"情報"][0][u"番号"], ensure_ascii=False)

実行結果

# ./sample.py sample.json
"東京"
Comments [0] | Trackbacks [0]

bashで小数点を比較する方法

November 6,2019 11:55 PM
Category:[bash]
Tag:[bash, linux]
Permalink

bashで小数点を比較する方法を紹介します。

1.問題点

小数点を比較したいのですが、下記の構文では期待する結果になりません。

#!/bin/bash
 
A=0.1
B=0.2
 
if [ $A -gt $B ]; then
    echo "A > B"
else
    echo "A <= B"
fi

実行結果

./test.sh
./test.sh: line 6: [: 0.1: 指数の表現を期待
A <= B

ということで、bashで小数点を比較する方法を紹介します。

2.bashで小数点を比較する

bashで小数点を比較するには、echoとbcコマンドを組み合わせます。

#!/bin/bash
 
A=0.1
B=0.2
 
if [ `echo "$A > $B" | bc` == 1 ]; then
    echo "A > B"
else
    echo "A <= B"
fi

実行結果

./test.sh
A <= B

bcは計算を処理するコマンドです。

if文の説明ですが、まず、

echo "$A > $B" | bc

で、変数Aと変数Bを比較し、結果を表示してくれます。

結果が偽(A <= B)であれば0、真(A > B)であれば1を出力します。

あとは出力結果(0または1)を判定すればOKです。

今回のサンプルでは、

if [ `echo "$A > $B" | bc` == 1 ]; then

なので、A > Bであればthenを実行し、A <= Bであればelseを実行します。

Comments [0] | Trackbacks [0]

Thunderbirdで重複メールを削除する方法

October 24,2019 11:55 PM
Category:[Thunderbird]
Tag:[Thunderbird]
Permalink

Thunderbirdで重複メールを削除する方法について紹介します。

1.はじめに

何かの拍子に受信メールが重複しまいました。

数千件あるので手作業ではなくツールなどを使って一括削除したいのですが、方法がわかりません。

ということで、Thunderbirdで重複メールを削除する方法について紹介します。

2.重複メールを削除する

Thunderbirdで重複メールを削除するには、拡張機能「Remove Duplicate Messages」を利用します。

Thunderbirdの「ツール」→「アドオン」を選択し、検索ボックスに「Remove Duplicate Messages」を入力して検索。

表示された「Remove Duplicate Messages」の「インストール」をクリック(インストール後は要再起動)。

重複メールを削除したいフォルダを選択し、「ツール」→「重複メッセージの削除」を選択。

すべての重複メールが検出されるので、問題なければ「OK」をクリック。

(クリックで拡大)

これで重複メールが削除されました。

重複メールの検出方法は「ツール」→「アドオン」→「拡張機能」→「Remove Duplicate Messages」の「設定」をクリックすればカスタマイズできます。

Comments [0] | Trackbacks [0]
 1  |  2  |  3  |  4  |  5  | All pages