【Linux】 umask コマンド

今回は知っているようで意外と奥が深い Linuxumask コマンドについて調べてみました。

何のためのコマンドなのか?

CentOS7 の環境で「man umask」と入力しました。

すると、BASH_BUILTINS のページが表示されました。

つまり、umask は bash のビルトインコマンドです。

BASH_BUILTINS(1)                                                                                        General Commands Manual                                                                                        BASH_BUILTINS(1)

NAME
       bash,  :,  .,  [,  alias, bg, bind, break, builtin, caller, cd, command, compgen, complete, compopt, continue, declare, dirs, disown, echo, enable, eval, exec, exit, export, false, fc, fg, getopts, hash, help, history, jobs,
       kill, let, local, logout, mapfile, popd, printf, pushd, pwd, read, readonly, return, set, shift, shopt, source, suspend, test, times, trap, true, type, typeset, ulimit, umask, unalias, unset, wait - bash  built-in  commands, ← umask は bash のビルトインコマンドです。
       see bash(1)

BASH BUILTIN COMMANDS
       Unless otherwise noted, each builtin command documented in this section as accepting options preceded by - accepts -- to signify the end of the options. 

特に明記されていないかぎり、このセクションでは、オプションの終わりを示すために - accepts - の前にacceptingオプションとして記述された各組み込みコマンドを使用します。

 

bash のビルトインコマンドとは?

ビルトインコマンドはあらかじめシェルに組み込まれている(ビルトインしている)コマンドです。

そのため、説明上は「umask」コマンドの実体(ファイル)は Linux 上には存在しないという前提です。

しかし「CentOS6」「CentOS7」「which」コマンドを実行してみると・・・

 

「CentOS6」の場合

[root@cent06 ~]# which umask
/usr/bin/which: no umask in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)

CentOS6上ではファイルが存在しません。

 

「CentOS7」の場合

[test@cnt07 ~]$ which umask
/usr/bin/umask ← umask の実体がありました。

 

この実体について調べてみますと・・・

[test@cnt07 ~]$ ls -l /usr/bin/umask
-rwxr-xr-x. 1 root root 29 12月  7  2016 /usr/bin/umask ← 実体があります。
[test@cnt07 ~]$ file /usr/bin/umask ← 「/usr/bin/umask」のファイルのタイプを確認します。
/usr/bin/umask: POSIX shell script, ASCII text executable ← シェルスクリプトであることが分かりました。
[test@cnt07 ~]$ cat /usr/bin/umask ← スクリプト?ということでスクリプトの内部を確認してみると・・・
#!/bin/sh
builtin umask "$@" ← やっぱりビルトインコマンドでした。
[test@cnt07 ~]$

 

若干混乱しますが、CentOS7 の場合も「umask」コマンドは「ビルトインコマンド」でした。

このシェルを解説しますと、以下のようになります。

#!/bin/sh
builtin umask "$@"

 

  • 「builtin」コマンドで「umask」コマンドを実行しています。
  • 「umask」コマンドは引数に「"$@"」を指定しています。

 

※ちなみに $@(ダブルクオーテーションで囲まない)"$@"(ダブルクオーテーションで囲む)は動作が異なります。

試しにスクリプトを作ってみました。

[root@cnt07 script]# vi test.sh
#!/bin/sh
~/script/sub.sh $@ ← 最初のスクリプトの引数は「$@」です。
~/script/sub.sh "$@" ← 次のスクリプトの引数は「"$@"」です。(ダブルクオーテーションで囲んでいます)

 

sub.shを作成します。

[root@cnt07 script]# vi sub.sh ← 同ディレクトリに「sub.sh」を作成します。
#!/bin/sh
echo "引数は $# です。" ← $# で引数の数をカウントします。
[root@cnt07 script]#

 

このスクリプトを実行します。

[root@cnt07 script]# ./test.sh 0022 ← 通常の umask コマンドを想定しています。
引数は 1 です。
引数は 1 です。
[root@cnt07 script]# ./test.sh "0022" ← ためしにダブルクオーテーションで囲んでみました。
引数は 1 です。
引数は 1 です。
[root@cnt07 script]# ./test.sh "00" "22" 
引数は 2 です。 ← どちらも引数2つです。
引数は 2 です。
[root@cnt07 script]# ./test.sh 00 22
引数は 2 です。 ← どちらも引数2つです。
引数は 2 です。
[root@cnt07 script]# ./test.sh "00 2" 2
引数は 3 です。 ← $@ はダブルクオーテーション関係なしにスペースで判断して引数3つでカウントしています。
引数は 2 です。 ← "$@" は、スペース関係なしにダブルクオーテーションで囲まれているのを1つとしてカウントしています。その結果引数が2つになっています。

 

ただ、umask コマンドの場合は引数は「0022」とか「022」などで、スペースが入る余地がないのですが、"$@"は「そのままの状態(パラメーターの構成や引数の数)」を引き渡しますので、より不測の事態が起こりにくくなると言えるでしょう。

 

ここまで話をしてきて今更ですが、「type」コマンドでも「ビルトインコマンド」「外部コマンド」かを確認することができます。

 

「CentOS6」の場合

[root@cent06 ~]# type -a umask
umask is a shell builtin

 

「CentOS7」の場合

[root@cnt07 script]# type -a umask
umask はシェル組み込み関数です ← どうやら umask は OS に 3つ認識されているようです。
umask は /bin/umask です
umask は /usr/bin/umask です

[root@cnt07 script]# cat /bin/umask
#!/bin/sh
builtin umask $@

[root@cnt07 script]# cat /usr/bin/umask
#!/bin/sh
builtin umask $@

 

[root@cnt07 script]# ls -l /bin/umask
-rwxr-xr-x. 1 root root 27  7月  4 22:03 /bin/umask
[root@cnt07 script]# ls -l /usr/bin/umask
-rwxr-xr-x. 1 root root 27  7月  4 22:03 /usr/bin/umask
[root@cnt07 script]#

 

 

3桁のパターンと、4桁のパターンで何が違うのか?

umaskコマンドについて調べると、「0022」と4桁で設定するパターンと「022」と3桁で設定するパターンがあります。

 

ためしに umask コマンドの検証をしてみます。

※「CentOS7」の場合

[test@cnt07 ~]$ umask ← 現在の設定を確認します。
0002
[test@cnt07 ~]$ umask 022 ← 3桁で umask コマンドを実行します。
[test@cnt07 ~]$ umask
0022 ← 問題なく設定されています。
[test@cnt07 ~]$ umask 0002 ← 4桁で umask コマンドを実行します。
[test@cnt07 ~]$ umask
0002 ← 問題なく設定されています。
[test@cnt07 ~]$

 

結論から言えば、3桁でも4桁でも正しく設定はできます。(エラーも出ません)

 

3桁で umask コマンドを実行すると先頭に0が入っている想定になる

3桁か4桁かどちらが正解か、どちらが正統派なのかは置いておいて、「umask 002」のように3桁の数字の引数を与えた場合、先頭にゼロが入って「umask 0002」としてコマンドが実行されます。

つまりゼロ(0)が省略されていると解釈します。

 

もし4桁目が存在している場合は「setuid ビット」「setgidビット」およびスティッキービット(sticky bit)」が設定されているものとして解釈をします。

 

数値の場合は

1 スティッキービット

2 setgid

4 setuid

になります。

 

umask コマンドはシンボルで表示ができる

umaskコマンドは「シンボル」で表示が可能です。

シンボルとは「rwx」などのことを言います。

[test@cnt07 ~]$ umask 0022
[test@cnt07 ~]$ umask -S
u=rwx,g=rx,o=rx
[test@cnt07 ~]$ umask 0002
[test@cnt07 ~]$ umask -S
u=rwx,g=rwx,o=rx
[test@cnt07 ~]$

 

umask はログイン時に設定される

大体 umask の設定がログイン後の「環境変数」設定ファイルで設定されます。

特にユーザーごとに「.bash_profile」などで設定されていない場合は「/etc/profile」の「umask」の設定が適応されます。

 

[test@cnt07 ~]$ cat /etc/profile
# /etc/profile

# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

pathmunge () {
    case ":${PATH}:" in
        *:"$1":*)
            ;;
        *)
            if [ "$2" = "after" ] ; then
                PATH=$PATH:$1
            else
                PATH=$1:$PATH
            fi
    esac
}

if [ -x /usr/bin/id ]; then
    if [ -z "$EUID" ]; then
        # ksh workaround
        EUID=`/usr/bin/id -u`
        UID=`/usr/bin/id -ru`
    fi
    USER="`/usr/bin/id -un`"
    LOGNAME=$USER
    MAIL="/var/spool/mail/$USER"
fi

# Path manipulation
if [ "$EUID" = "0" ]; then
    pathmunge /usr/sbin
    pathmunge /usr/local/sbin
else
    pathmunge /usr/local/sbin after
    pathmunge /usr/sbin after
fi

HOSTNAME=`/usr/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
    export HISTCONTROL=ignoreboth
else
    export HISTCONTROL=ignoredups
fi

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL

# By default, we want umask to get set. This sets it for login shell
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
    umask 002
else
    umask 022
fi

for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null
        fi
    fi
done

unset i
unset -f pathmunge
[test@cnt07 ~]$

 

具体的に何をチェックしているのかと言いますと、

[ $UID -gt 199 ]  ← UIDが199より上であるか?

とチェックをしています。

 

test アカウントの uid は 1000 なので 199 より上です。

[test@cnt07 ~]$ cat /etc/passwd | grep test
test:x:1000:1000:test:/home/test:/bin/bash

 

次に

「/usr/bin/id -gn」コマンドは グループ名を表示するコマンドです。

「-gn」オプションでグループ名を表示します。

[test@cnt07 ~]$ /usr/bin/id -gn
test

 

次に

「/usr/bin/id -un」コマンドはユーザー名を表示するコマンドです。

「-un」オプションでユーザー名を表示します。

[test@cnt07 ~]$ /usr/bin/id -un
test

 

つまり、

  • UIDが199以上で「ユーザー名」と「グループ名」が同じ場合  → 「umask 0002」で設定される
  • UIDが199以上で「ユーザー名」と「グループ名」が異なる場合 → 「umask 0022」で設定される

です。

 

その理由は、

  • 「ユーザー名」と「グループ名」が一緒  → 所有者とグループを一緒の権限にしても問題なし
  • 「ユーザー名」と「グループ名」が異なる → グループには他のユーザーも含まれる可能性があるから、所有者にのみ全権限(読み書き実行)を与える

ということです。

 

まとめ

umaskコマンド1つ取っても、なかなか奥が深かったです。

設定も単純そうですが実は様々な環境や要素がからんでいます。

 

 

Posted by 100%レンタルサーバーを使いこなすサイト管理人

コメントを残す

メールアドレスが公開されることはありません。