- 投稿日:2020-08-17T23:59:10+09:00
【bash】におけるクォートの扱い
背景
bashを書き始めたばかりの新米エンジニアです。コーディングしていて、
”あれ、ここシングルクォート?ダブル?そもそも囲う必要あるのかな?まぁ動けばなんでもいいか・・・”
という具合にいつも悩んでしまうので、改めて整理することにした。結論
シングルクォート''
文字列をシングルクォートで囲むと、文字列中の各文字すべてが特殊な意味を失い、文字通りの意味として解釈される。
# $HOMEはシェルを実行中のユーザのホームディレクトリが設定されている特別なシェル変数 $ echo '$HOME' # シングルクォートで囲む $HOME # そのまま$HOMEと出力される $ echo "$HOME" # ダブルクォートで囲む /c/Users/guest.name # シェル変数の値に展開される $ echo '*' # シングルクォートで囲む * # そのまま*と出力される $ echo * # 何もクォートしない bin doc src # カレントディレクリのファイル名に展開されるダブルクォート""
文字列をダブルクォートで囲むと、シングルクォートとほぼ同様にほとんどの文字がその特殊な意味を失う。
しかし、\$と`の特殊な意味は残るため、パラメータ展開とコマンド置換は行われる。
予期せぬ挙動を防ぐために、"\$変数" や "\$(コマンド置換)" はダブルクォートで囲んだほうが良さそう。# パラメータ展開 $ var='*** hello world ***' # スペースの連続と*を含む文字列 $ echo "$var" # ダブルクォートで囲む *** hello world *** # 正しく表示される $ echo $var # ダブルクォートで囲まない bin doc src hello world bin doc src # スペースが区切り文字として解釈され、前後にカレントディレクトリのファイル名が展開される # コマンド置換 $ user='$(whoami)' # シングルクォートで囲む $ echo "$user" $(whoami) # 単なる文字列として解釈されている $ user="$(whoami)" # ダブルクォートで囲む $ echo "$user" guest.name # whoamiコマンドの結果が代入されているバックスラッシュ\
文字の前にバックスラッシュををつけると、\の直後の1文字が特殊な意味を失い、文字通りの意味として解釈される。
$ echo \$HOME # $の前にバックスラッシュをつける $HOME # そのまま$HOMEと出力される $ echo $HOME # バックスラッシュをつけないと /c/Users/guest.name # シェル変数の値に展開される $ echo \* # *の前にバックスラッシュをつける * # そのまま*と出力される $ echo * # バックスラッシュをつけないと bin doc src # カレントディレクリのファイル名に展開される参考文献:山森 丈範 『[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる』 技術評論社 (2018/11/14)
- 投稿日:2020-08-17T23:59:10+09:00
【bash】におけるクォートの使い分け
背景
bashを書き始めたばかりで使い分けに迷ったので、改めて整理することにした。
初心者の方は参考にしてください。結論
シングルクォート''
囲われた文字すべてが特殊な意味を失います。
業務ではファイルにヘッダーをつける時など、単純な文字列を出力したい時に使っています。
echo 'colomn1 column2 column3' > file1以下サンプル
# $HOMEはシェルを実行中のユーザのホームディレクトリが設定されている特別なシェル変数 $ echo '$HOME' # シングルクォートで囲む $HOME # そのまま$HOMEと出力される $ echo "$HOME" # ダブルクォートで囲む /c/Users/guest.name # シェル変数の値に展開される $ echo '*' # シングルクォートで囲む * # そのまま*と出力される $ echo * # 何もクォートしない bin doc src # カレントディレクリのファイル名に展開されるダブルクォート""
パラメータ展開、コマンド置換を行う時につけるものと解釈して良さそう。
アスタリスク(*)やスペース( )といった、特殊な文字が解釈されて予期せぬ挙動を引き起こすことがあるのでつけたほうが良いらしい。testコマンドの判定に変数を使ったり
[ -z "$var" ] # 変数$varが空かどうかを判定する条件式コマンド置換でファイルリストを取得したりする際に使っています。
file_list="$(ls /home/data/*.csv)"以下サンプル
# パラメータ展開 $ var='*** hello world ***' # スペースの連続と*を含む文字列 $ echo "$var" # ダブルクォートで囲む *** hello world *** # 正しく表示される $ echo $var # ダブルクォートで囲まない bin doc src hello world bin doc src # スペースが区切り文字として解釈され、前後にカレントディレクトリのファイル名が展開される # コマンド置換 $ user='$(whoami)' # シングルクォートで囲む $ echo "$user" $(whoami) # 単なる文字列として解釈されている $ user="$(whoami)" # ダブルクォートで囲む $ echo "$user" guest.name # whoamiコマンドの結果が代入されているバックスラッシュ\
文字の前にバックスラッシュををつけると、\の直後の1文字が特殊な意味を失い、文字通りの意味として解釈される。
$ echo \$HOME # $の前にバックスラッシュをつける $HOME # そのまま$HOMEと出力される $ echo $HOME # バックスラッシュをつけないと /c/Users/guest.name # シェル変数の値に展開される $ echo \* # *の前にバックスラッシュをつける * # そのまま*と出力される $ echo * # バックスラッシュをつけないと bin doc src # カレントディレクリのファイル名に展開される参考文献:山森 丈範 『[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる』 技術評論社 (2018/11/14)
- 投稿日:2020-08-17T17:52:49+09:00
LinuxのVLCの回転ができなくなったときの対処
Preferences -> Input/Codecs -> Disable hw decoding
- 投稿日:2020-08-17T16:23:28+09:00
Parallels Desktop 16 for Mac で CentOS 7 を目立たないようにコマンド起動
Macユーザーですが、Windows 10 も顧客のサポートのために必要なことがあるので、 Parallels Desktop は導入済みでした。
一方、MacでLinuxのアプリ開発において使うような imagemagik だとか、Vue.js とか、もっと言えば rbenv なんかでさえも、 「Macの環境を汚すのでインストールしたくない!」 という説明しがたい感情がありました。
そこで、Parallels Desktopに、CentOS 7 を導入して、そのVMボリューム(ファイル)の中でこういった「汚い?」ことは完結させることにしました。
Parallels Desktopでの CentOS 7の導入自体の説明は省きますが、それをコマンド起動したり、Parallelsのアプリのウィンドウを表示しなくしたりといった設定を以下にまとめます。※Parallels Desktop 16の現時点です。
ParallelsでCentOS 7 をインストールが終わると、
Parallels
というユーザーがデフォルトで作られ、GNOME が起動し、Parallels
パスワードを設定してくださいという画面になりパスワードを決めて入力します。そこまでは、とりあえず終えているとします。Macターミナルからのssh接続
Paralells では、CentOSを起動中、Macの
/etc/hosts
に、自動的に以下が追加されるようです。(10.XXX.XX.X
の部分はParalellsが自動で決めたVMのIPアドレスです)10.XXX.XX.X centos7.shared centos7 #prl_hostonly sharedですので、Macのターミナルアプリから
% ssh paralells@centos7 parallels@centos7's password:で接続できます。パスワードは、最初に設定したパスワードです。
ParalellsのCentOSを終了すると、/etc/host
は自動的に元に戻るようです。Dockerなどは root でインストールしたい
parallelsユーザーは、
wheel
を付加されているのでsudoが使えるのですが、いっそ、rootユーザーになってしまった方が楽ちんです。そこで、root
のパスワードも変えてしまします。
parallelsユーザーでsudo
でsu -
してroot
になって、passwd
します。[parallels@centos7 ~]$ groups $USER parallels : parallels wheel [parallels@centos7 ~]$ sudo su - [sudo] parallels のパスワード: 最終ログイン: 2020/08/17 (月) 15:31:06 JST日時 pts/0 [root@centos7 ~]# passwd Changing password for user root. New password: Retype new password: passwd: all authentication tokens updated successfully. [root@centos7 ~]#これで、Macのターミナルから、
% ssh root@centos7 root@centos7's password:でログインできるようになり、
Docker や git、環境に必要なライブラリをrootでインストールできます。さらに、僕は開発用のユーザーを追加して、普段はこちらでログインして使うことにしています。
[root@centos7 ~]# useradd development
/home/development
ディレクトリを開発専用にします。(ParalellsユーザはGNOMEログインしてしまっているので、Desktop, Documentsといった不要なディレクトリがあるので、GNOMEログインしないユーザとしてdevelopmentを設置)VMをコマンド起動したい
Parallelsのアプリをいちいち起動するのではなく、VM毎にコマンド起動するには
% prlctl start <VMの名前>で起動できます。CentOS 7のデフォルトのVM名は
CentOS 7
なので、起動コマンドを簡単にするために、VMの設定で名前を変更しておきます。例えばcentos7
としておけば少し楽です。
各コマンドは以下のようです(説明省力)。
% prlctl start centos7 % prlctl stop centos7 % prlctl restart centos7 % prlctl pause centos7 % prlctl resume centos7 % prlctl list --allParallelsのウィンドウは要らない
CentOSでコマンドしか使わないのであれば、Paralellsのウィンドウも不要です。
表示しない設定がちゃんとありました。% prlctl set centos7 --on-window-close keep-runningまとめ
以上の設定をすれば、
Macのターミナルアプリから、VMの起動から、開発作業、終了まで一連のことがコマンドだけでできるようになります。% prlctl start centos7 Starting the VM... The VM has been successfully started. % ssh development@centos7 development@centos7's password: Last login: Mon Aug 17 15:30:51 2020 from 10.211.55.2 [development@centos7 ~]$ …… …… <CentOS上で開発など> …… …… [development@centos7 ~]$ exit ログアウト Connection to centos7 closed. % prlctl stop centos7 Stopping the VM... The VM has been successfully stopped. %Paralellsのウィンドウが表示されることもなく、「静かに?」仕事ができます。
注意点は、startからsshログインできるまでに、当然起動のためのタイムラグが少しあることと(すぐにはsshできない)、 stop することを忘れないこと(使わないならCPUとメモリ資源のムダ)。
なお、Macのファイルは
/media/psf
以下にあります。
- 投稿日:2020-08-17T15:45:02+09:00
gpgでHTTP fetch errorが出て鍵が取得できないエラーの対処
TL;DR
- hkpのポートは通常11371
gpg --keyserver hkp://keyserver.ubuntu.com:80
のように利用出来るポートを指定するといい状況
社内仮想ホスト上のcentos7にpritunlをインストールしようとした際、下記のようなエラーが出ました
$ gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys CF8E292A gpg: 鍵CF8E292Aをhkpからサーバkeyserver.ubuntu.comに要求 gpgkeys: HTTP fetch error 56: Recv failure: Connection reset by peer gpg: 有効なOpenPGPデータが見つかりません。hkpのポートは通常11371を利用します。今回利用した仮想ホストはセキュリティ設定によりアウトバウンドの11371が許可されていなかった為エラーになっていました。
$ cat /etc/services | grep hkp pgpkeyserver 11371/tcp hkp # PGP/GPG public keyserver pgpkeyserver 11371/udp hkp # PGP/GPG public keyserveryum出来る環境であれば80番等使えると思うので、:80を指定。
$ gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys CF8E292A gpg: 鍵CF8E292Aをhkpからサーバkeyserver.ubuntu.comに要求 gpg: 鍵CF8E292A: 公開鍵"Pritunl <contact@pritunl.com>"をインポートしました gpg: 処理数の合計: 1 gpg: インポート: 1 (RSA: 1)上手くいきました
- 投稿日:2020-08-17T05:49:45+09:00
RedHat 設定確認コマンド
確認コマンド.logfdisk -l df -hT swapon -s cat /etc/fstab hostnamectl status systemctl list-unit-files -t service | cat cat /etc/group cat /etc/passwd #/etc/sysconfig/network-scripts/eth0 nmcli device show | cat grep PermitRootLogin /etc/ssh/sshd_config grep AllowUsers /etc/ssh/sshd_config firewall-cmd --get-active-zones firewall-cmd --list-all --permanent firewall-cmd --list-ports --zone=public --permanent cat /etc/redhat-release uname -a localectl status df -hT swapon hostname cat /etc/hosts ip addr ip route timedatectl status | grep Tokyo getenforce systemctl status kdump.service systemctl status sendmail.service systemctl status postfix.service systemctl status dovecot systemctl status httpd systemctl status postgresql-server systemctl list-unit-files | grep kdump systemctl list-unit-files | grep sendmail systemctl list-unit-files | grep postfix systemctl list-unit-files | grep dovecot systemctl list-unit-files | grep httpd systemctl list-unit-files | grep postgresql-server systemctl list-unit-files | grep chronyd grep server /etc/chrony.conf cat /etc/resolv.conf who -r systemctl list-unit-files -t service | cat yum list installed netstat -auntpl
- 投稿日:2020-08-17T01:59:01+09:00
all arch: remove system call sys_sysctl
カーネルのcommit logを見てたら、全アーキテクチャに関わる修正があった。なんだろうこれ?というメモ。
TL;DR:ある機能を削除する事は難しい
これ、最初の段階からすると、10年がかりですね。本当に関係者の方々、ありがとうございます、お疲れ様でした。
時系列に並べていくと…
[PATCH] sysctl: Allow /proc/sys without sys_sysctl ( 2006/09/27 )
Since sys_sysctl is deprecated start allow it to be compiled out. This should catch any remaining user space code that cares, and paves the way
for further sysctl cleanups.sys_sysctlは廃止予定なので、コンパイル対象外にし始めます。残りのユーザー空間コードをキャッチし、更なるsysctlクリーンアップに向けて道を開くはずです。
sysctl: Separate the binary sysctl logic into it's own file. ( 2006/11/06)
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=61a47c1ad3a4dc
In preparation for more invasive cleanups separate the core binary sysctl logic into it's own file.
より侵略的なクリーンアップに向けて、core binary sysctl logicを独自のファイルへ分離します。
sysctl: Remove the sysctl system call ( 2019/11/26 )
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=61a47c1ad3a4dc
This system call has been deprecated almost since it was introduced, and in a survey of the linux distributions I can no longer find any of them that enable CONFIG_SYSCTL_SYSCALL. The only indication that I can find that anyone might care is that a few of the defconfigs in the kernel enable CONFIG_SYSCTL_SYSCALL. However this appears in only 31 of 414 defconfigs in the kernel, so I suspect this symbols presence is simply because it is harmless to include rather than because it is necessary.
As there appear to be no users of the sysctl system call, remove the code. As this removes one of the few uses of the internal kernel mount of proc I hope this allows for even more simplifications of the proc filesystem.
このsystem callは導入された時点から非推奨であり、Linuxディストリビューションの調査では、CONFIG_SYSCTL_SYSCALLを有効にするディストリビューションはもう見つかりません。これに対して気に掛ける誰がいるかどうかを検出する唯一の方法は、カーネル内のいくつかのdefconfigでCONFIG_SYSCTL_SYSCALLを有効にすることです。ただし、これはカーネルのdefconfigの414中31にしか現れません。そのため、私はこのシンボルの存在は、必要ではなく、含まれても無害と考えます。
sysctl system callのユーザーがいないように見えるため、このコードを削除します。procの内部カーネルマウントの数少ない使用方法が削除されます。proc filesystemが更に単純化されることを期待しています。
all arch: remove system call sys_sysctl (2020/08/16 )
all arch: remove system call sys_sysctl
Since commit 61a47c1ad3a4dc ("sysctl: Remove the sysctl system call"), sys_sysctl is actually unavailable: any input can only return an error.We have been warning about people using the sysctl system call for years and believe there are no more users. Even if there are users of this interface if they have not complained or fixed their code by now they probably are not going to, so there is no point in warning them any longer.
So completely remove sys_sysctl on all architectures.
all arch: system call sys_sysctlを削除する。
commit 61a47c1ad3a4dc ("sysctl: Remove the sysctl system call")以来、sys_sysctl は実質無効であった: 入力に関わらずエラーを返す。sysctl system callを利用するユーザーに対して長年警告を続け、更なるユーザーはいないものと確信した。このインターフェイスを使用しているユーザーがいても、コードに対する不満や修正をしていない場合は、おそらくそうするつもりはないはずであり、警告する意味はもう無い。
そこで、sys_sysctlを全アーキテクチャで完全に削除します。結論:ある機能を削除する事は難しい
これ、最初の段階からすると、10年がかりですね。本当に関係者の方々、ありがとうございます、お疲れ様でした。
- 2009/09/27 deprecate予定なので、コンパイル対象外にできるようにコンフィグレーションに追加。
- 2009/11/06 機能をクリーンアップのために分離。この時点でdeprecated.
- 2019/11/26 削除するための機能無効化
- 2020/08/16 機能完全削除
「本当にこのコードを消していいのか?」をどうやって確定させるのか、ということを含めて、難しいものだなあと考えさせられました。