シェルスクリプトの動作について

質問は2 つです。シェルスクリプトを起動時にlaunchd から読んだ際にType A とType B の動作の違いは何故か。

memory_pressure コマンドを読んだ際に、再起動前のFinder のウインドウが開かなくなるのは何故か。

です。


状況ですが、

勉強がてら下記のシェルスクリプトを作りました。勉強しながら作ったので、その手の人が見るとダメダメな可能性が高いすが、どうにも不思議な動きをするので質問することとしました。

下記のシェルスクリプトはThunderbolt 接続の外付けSSD から起動したさいにVM パーティションをマウントするためのものです。

Type A

#!/bin/bash -x



set -eu



UUID=「自分のところのUUID」

mountpoint=""

tpoint="/private/var/vm"

vmSwap="vm.swapusage: total = 0.00M"

swapfile="vm.swapusage: total = 0.00M"



sleep 7



for n in $(seq 1 5)

do

if [ "$mountpoint" = "$tpoint" ] ; then

echo $((n - 1)) >> /Users/Shared/n.txt

else

set +e

diskutil mount -mountPoint /private/var/VM "$UUID"

set -e



sleep 4

mountpoint=$(diskutil info "$UUID" | grep -o "$tpoint")

echo ${mountpoint}" xx" >> /Users/Shared/n.txt

fi

done



set +e

memory_pressure -l critical 2>&1 &

set -e



sleep 7



set +e



for n in $(seq 1 61)

do

if [ "$swapfile" = "$vmSwap" ] ; then

sleep 2

swapfile=$(sysctl vm.swapusage | grep -o "$vmSwap")

else

killall -15 -e memory_pressure

exit 0

fi

done

それでType B

#!/bin/bash



UUID=「自分のところのUUID」

mountpoint=“”

mou="vate/var/vm (apfs, local, nodev, nosuid, journaled, noowners, nobrowse)"



for n in `seq 1 14`

do

if [ "$mou" = "$mountpoint" ] ; then

echo $n >> /Users/Shared/Logs/n.txt

exit

else

diskutil mount -mountPoint /private/var/vm $UUID

fi



sleep 3

mountpoint2=`mount | grep "s4 on /private/var/vm (apfs,"`

mountpoint=${mountpoint2##*pri}

done

提載状態なら、どちらも正常に動きます。

それで、

最初の質問はType A の8 行目「sleep 7」です。Mac によってはこの「7」が4 以下になると動きません。動かないのにエラーは出ません。ログによれば目的のパーティションはマウントされて終了しています。ところがログイン後、確認するとマウントされていません。

これは何故でしょうか。これが第一の質問です。


第二の質問ですが、Type A のmemory_pressure コマンドです。

何故かType A の上記のコマンドを実行するとMac を起動してログインしたさいに再起動前に開いていたウインドウが開かなくなる症状があります。私のところでは再現性は高いのですが、気まぐれに起きなくなったりします。気まぐれに直るのは良いのですが何故、起きるのでしょうか。


macOS High Sierra 10.13.4

投稿日 2018/04/15 04:44

返信
返信: 29

2018/04/18 09:59 ni_ki への返信

横から失礼します。


サラッと試してみましたがAgents の方はroot 権限で実行されるのではないのですね。管理者権限だとsudo が必要になるのでexpect の方に戻さないといけないようです。


セキュリティ的にはちょっとアレだけど...、こんな感じで sudo の -S オプションを使ってみてはどうでしょうか?

echo 'password' | sudo -S whoami

2018/04/19 03:40 hohokihai への返信

検証、感謝申し上げます。

どうも起動やログイン時のマウント系が不思議な動作をするようですね。もしかして外付けAPFS から起動すると、vm パーティションをマウントしないのもスワップファイルを作成しないのも、似た原因なのかと勘ぐってしまいます。


ちなみに別の外付けSSD を指定したら見事にマウントされてスワップもできました。何か楽しいですね。

2018/04/23 19:49 ni_ki への返信

2台のmacOS High Sierra 10.13.4 で起動時に数分間フリーズするので、このスクリプトが原因かと思っていたらカスペルスキー18.0.1.35b が原因でした。スクリプトを外しても起きます。

一昨日くらいまでは起きなかったので何が原因か不明ですが、アップデートを自動にしているのでカスペルスキーがアップデートされたのかと思います。

カスペルスキーをお使いの方はご注意を。

2018/04/17 04:04 hohokihai への返信

hohokihai さんによる書き込み:


8行目のsleepがないと動かないとのことですが、不可解ですね。seqの数を増やしてもだめなんですか?

厳密には動かないのではなくログによれば1 回目のdiskutil mount の実行でマウントを完了して正常終了しているようです。ところがログインが完了してから確認するとマウントされていません。seq の方は1 回目ので正常完了とされているので増やしても動作に変わりありません。

というわけで、私ならこうします。


device=$( diskutil mount -mountPoint /private/var/vm $UUID | swk '{ print $4 }') mounted=0 if [ $device != "" ]; then for n in $(seq 0 120); do if [ $mounted -eq 1 ]; then echo $n >> /Users/Shared/Logs/NumberOfSeconds.txt break else mounted=$(df -b -T apfs | grep -c $device) fi sleep 1 done fi


確認してみたのですがdf コマンドの行の「grep -c $device」ですが、このgrep はUUID が含まれる行数を計算するものでしょうか。

2018/04/17 23:07 ni_ki への返信

実は私、起動時にRamdiskをmountするアプリを作っているのですが、Yosemiteの頃からmacOSが勝手にunmountするようになったので、mountする直前にdiskarbitrationdやfseventsdをkillして凌いでいました。(それでもunmountされてしまうこともありました)


Yosemiteではsystem.logにkernelがunmountしたとのログが残っていましたが(mountしてから約8秒後)、Sierraではsystem.logにも記録されなくなりました。これらはセキュリティ強化の一環なのでしょう。


その後、フォーマットをHFS+からGPTに変えたら、小細工せずともunmountされなくなったので(High Sierraにした現在でも動いています)、GPTコンテナの中にあるAPFSも問題ないと思ったのですが、今回の場合ももしかするとmacOSが勝手にunmountしているのかもしれません。


mountした直後に、macOSが勝手にunmountしているのであれば、diskutil mountを連続して行うのも仕方がないのかもしれません。しかし何故、連続で行えば成功するのか釈然としません。


> dfコマンドの行の「grep -c $device」ですが、このgrepはuuidが含まれる行数を計算するものでしょうか。


$deviceには「disk1s4」が入っている筈です。従って、grepは「disk1s4」が含まれる行数です。


launchd.plistは、/Library/LaunchDaemonsに入れてます?/Library/LaunchAgentsですか?


ところで今回の動機は、APFSでフォーマットした外部SSDから立ち上げたとき/var/vmが起動時にマウントされない問題絡みですよね?


MacBookであれば、下記を設定すればバッテリーがなくならない限りスリープしなくなるので、/var/vm/sleepimageの書き換えはまず起こらなくなり、/var/vmをマウントせずとも平気かもしれません...?


sudo pmset -a autopoweroffdelay 90000 # 25h

sudo pmset -a hibernatemode 0

sudo pmset -a standby 0

2018/04/18 07:01 hohokihai への返信

やっぱりUUID ですよね。マッチングする文字列を変更いたしました。ただやはり最初にsleep 5 とかを入れないと不安定なようです。

また再起動でウインドウがすべて閉じる症状はmemory_pressure コマンドが原因ではないようです。hohokihai さんのスクリプトでも発生しました。何かのタイミングのようですね。

またお示しのVM パーティションの4.3GB はパーティションの使用量だと思われます。

私にところで試した際には30GB くらいまではスワップいたしました。

Launched のplist の置き場所は試してみます。

ありがとうございます。

2018/04/21 06:09 ni_ki への返信

前にも書き込んでいますが、やはりdiskutil mount コマンドを使う前に時間を置くのが最善なようです。

sleep 17

くらいから、我が家の複数のMac で安定します。


ちなみに別ストレージをVM にマウントしていて、それを強制的にアンマウントするとクラッシュします。当然ですね。

2018/05/09 05:33 ni_ki への返信

> diskutilコマンドはnoatimeの設定ができない様です。

マウントした後でも-uフラグを付けることでマウントオプションの変更が可能です。(diskutilの後にmountするのは二度手間ですが...)

ユーザがアップロードしたファイル

> 質問の2つ目が、sleepコマンドで回避できません。

mountに比べ、diskutilは動作が遅いので、sleepを5秒程多めに設定してもだめですか?

このスレッドはシステム、またはAppleコミュニティチームによってロックされました。 問題解決の参考になる情報であれば、どの投稿にでも投票いただけます。またコミュニティで他の回答を検索することもできます。

シェルスクリプトの動作について

Apple サポートコミュニティへようこそ
Apple ユーザ同士でお使いの製品について助け合うフォーラムです。Apple Account を使ってご参加ください。