在 Bash Shell 脚本中检查常规文件和目录所有权以及组成员身份
Checking Regular File and Directory Ownership and Group Membership in a Bash Shell Script
我在 Bash 3.2.57(1) 中编写 shell 脚本-在 Solaris 10 下发布(uname -a 产生 "SunOS hostname 5.10 Generic_150400-35 sun4v sparc sun4v")。
我要解决的最终问题是,在 bash shell 脚本中,确定常规文件或目录的所有者和组成员身份。
很遗憾,我无法使用统计数据。
由于 stat 不可用,我知道的下一个最好的事情是从 ls -l 的输出中解析所有者和组成员身份。我不喜欢这种方法,以防万一可移植性成为问题,万一我遇到带有特殊字符的文件名会导致解析失败。但是,解析 ls -l 的输出是我目前得到的...
这引出了两个问题。
问题一
在 缺少 stat 并且 排除 ls -l 作为解决方案的一部分的情况下,是否有可接受的,在我的特定平台(Bash 3.2.57(1)-Solaris 10 下的发行版)上确定常规文件或目录的所有者和组成员身份的不太老套的方法?
在谷歌搜索中,这似乎是一个真正的挑战。
如果有人对解析 ls 的替代方法有任何建议,我将不胜感激。
问题二
这是我目前通过解析 ls -l 输出的最佳尝试:
#!/usr/bin/bash
###
###
###
# This functions returns success if:
# 1. The ownership of the pass file is root AND
# 2. The group membership of the passed file is root
#
# This function returns failure otherwise.
function check_if_ownership_and_group_membership_are_root
{
if [[ $# -ne 1 ]]; then
echo
echo "Usage: ${FUNCNAME[0]} <filename>"
echo "Actual (incorrect) usage: ${FUNCNAME[0]} $*"
echo "ABORTING SCRIPT; Failure point is designated \"Point 1\""
exit 1
fi
local FILENAME=""
# Check ownership of "${FILENAME}".
if [[ $(ls -l "${FILENAME}" | awk '{print }')="root" ]]; then
echo
echo "Part 1: Test of ownership being root supposedly passed"
echo "Actual ownership: " $(ls -l "${FILENAME}" | awk '{print }')
# The test of ownership being root passed. Continue on to test the group membership being root.
else
echo
echo "Part 2: Test of ownership being root supposedly failed"
echo "Actual ownership: " $(ls -l "${FILENAME}" | awk '{print }')
# The test of ownership being root did not pass. Return failure.
return 1
fi
# Check the group membership of "${FILENAME}".
if [[ $(ls -l "${FILENAME}" | awk '{print }')="root" ]]; then
echo
echo "Part 1: Test of group membership being root supposedly passed"
echo "Actual group membership: " $(ls -l "${FILENAME}" | awk '{print }')
# The ownership test previously passed, and now the group membership test passed.
# Return success.
return 0
else
echo
echo "Part 2: Test of group membership being root supposedly failed"
echo "Actual group membership: " $(ls -l "${FILENAME}" | awk '{print }')
# The test of group membership being root did not pass. Return failure.
return 1
fi
# Should never be able to get here. Abort the script.
echo
echo "ABORTING SCRIPT; Failure point is designated \"Point 2\""
exit 1
}
# Show what ls is being invoked.
echo "Here is what ls will be used:"
type ls
# For this example, I'll just use ad hoc file test.txt to demonstrate the problem I'm having.
FILENAME=./test.txt
touch "${FILENAME}"
###
###
###
# Test the success case of the file ownership being root and the file group membership being root.
chown root "${FILENAME}"
chgrp root "${FILENAME}"
# Display the actual file ownership and group membership.
echo
echo "Test of success case starting; here's the file being tested:"
ls -l "${FILENAME}"
# Perform the check of ownership being "root" and group membership being "root".
if check_if_ownership_and_group_membership_are_root "${FILENAME}"; then
echo
echo "FINAL RESULT: SUCCESS"
else
echo
echo "FINAL RESULT: FAILURE"
fi
###
###
###
# Test the failure case of the file ownership not being root or the file group membership not being root.
chown nobody "${FILENAME}"
chgrp other "${FILENAME}"
# Display the actual file ownership and group membership.
echo
echo "Test of failure case starting; here's the file being tested:"
ls -l "${FILENAME}"
# Perform the check of ownership being "root" and group membership being "root".
if check_if_ownership_and_group_membership_are_root "${FILENAME}"; then
echo
echo "FINAL RESULT: SUCCESS"
else
echo
echo "FINAL RESULT: FAILURE"
fi
这导致以下输出:
bash-3.2# ./script.sh
Here is what ls will be used:
ls is /usr/bin/ls
Test of success case starting; here's the file being tested:
-rw------- 1 root root 16 Aug 25 13:34 ./test.txt
Part 1: Test of ownership being root supposedly passed
Actual ownership: root
Part 1: Test of group membership being root supposedly passed
Actual group membership: root
FINAL RESULT: SUCCESS
Test of failure case starting; here's the file being tested:
-rw------- 1 nobody other 16 Aug 25 13:34 ./test.txt
Part 1: Test of ownership being root supposedly passed
Actual ownership: nobody
Part 1: Test of group membership being root supposedly passed
Actual group membership: other
FINAL RESULT: SUCCESS
可以看出,我使用 "if" 语句测试的条件总是通过。我做错了什么?
(尽管我希望有人能指导我远离解析 ls,但为了教育起见,无论如何我仍然想知道这个问题的答案。)
在此先感谢所有响应者。
比较运算符两边需要空格 =
:
[[ $(ls -l "${FILENAME}" | awk '{print }') = "root" ]]
另外,当你用双括号[[ ... ]]
.
写条件时,你应该使用==
而不是=
一般不推荐依赖ls的输出
if ! [[ $(stat --format '%G' "${FILENAME}") = "root" ]]; then
echo "do the thing"
fi
Shellcheck wiki 讨论了依赖 ls 输出的一些陷阱:https://github.com/koalaman/shellcheck/wiki/SC2012
引用:
ls
is only intended for human consumption: it has a loose,
non-standard format and may "clean up" filenames to make output easier
to read.
我在 Bash 3.2.57(1) 中编写 shell 脚本-在 Solaris 10 下发布(uname -a 产生 "SunOS hostname 5.10 Generic_150400-35 sun4v sparc sun4v")。
我要解决的最终问题是,在 bash shell 脚本中,确定常规文件或目录的所有者和组成员身份。
很遗憾,我无法使用统计数据。
由于 stat 不可用,我知道的下一个最好的事情是从 ls -l 的输出中解析所有者和组成员身份。我不喜欢这种方法,以防万一可移植性成为问题,万一我遇到带有特殊字符的文件名会导致解析失败。但是,解析 ls -l 的输出是我目前得到的...
这引出了两个问题。
问题一
在 缺少 stat 并且 排除 ls -l 作为解决方案的一部分的情况下,是否有可接受的,在我的特定平台(Bash 3.2.57(1)-Solaris 10 下的发行版)上确定常规文件或目录的所有者和组成员身份的不太老套的方法?
在谷歌搜索中,这似乎是一个真正的挑战。
如果有人对解析 ls 的替代方法有任何建议,我将不胜感激。
问题二
这是我目前通过解析 ls -l 输出的最佳尝试:
#!/usr/bin/bash
###
###
###
# This functions returns success if:
# 1. The ownership of the pass file is root AND
# 2. The group membership of the passed file is root
#
# This function returns failure otherwise.
function check_if_ownership_and_group_membership_are_root
{
if [[ $# -ne 1 ]]; then
echo
echo "Usage: ${FUNCNAME[0]} <filename>"
echo "Actual (incorrect) usage: ${FUNCNAME[0]} $*"
echo "ABORTING SCRIPT; Failure point is designated \"Point 1\""
exit 1
fi
local FILENAME=""
# Check ownership of "${FILENAME}".
if [[ $(ls -l "${FILENAME}" | awk '{print }')="root" ]]; then
echo
echo "Part 1: Test of ownership being root supposedly passed"
echo "Actual ownership: " $(ls -l "${FILENAME}" | awk '{print }')
# The test of ownership being root passed. Continue on to test the group membership being root.
else
echo
echo "Part 2: Test of ownership being root supposedly failed"
echo "Actual ownership: " $(ls -l "${FILENAME}" | awk '{print }')
# The test of ownership being root did not pass. Return failure.
return 1
fi
# Check the group membership of "${FILENAME}".
if [[ $(ls -l "${FILENAME}" | awk '{print }')="root" ]]; then
echo
echo "Part 1: Test of group membership being root supposedly passed"
echo "Actual group membership: " $(ls -l "${FILENAME}" | awk '{print }')
# The ownership test previously passed, and now the group membership test passed.
# Return success.
return 0
else
echo
echo "Part 2: Test of group membership being root supposedly failed"
echo "Actual group membership: " $(ls -l "${FILENAME}" | awk '{print }')
# The test of group membership being root did not pass. Return failure.
return 1
fi
# Should never be able to get here. Abort the script.
echo
echo "ABORTING SCRIPT; Failure point is designated \"Point 2\""
exit 1
}
# Show what ls is being invoked.
echo "Here is what ls will be used:"
type ls
# For this example, I'll just use ad hoc file test.txt to demonstrate the problem I'm having.
FILENAME=./test.txt
touch "${FILENAME}"
###
###
###
# Test the success case of the file ownership being root and the file group membership being root.
chown root "${FILENAME}"
chgrp root "${FILENAME}"
# Display the actual file ownership and group membership.
echo
echo "Test of success case starting; here's the file being tested:"
ls -l "${FILENAME}"
# Perform the check of ownership being "root" and group membership being "root".
if check_if_ownership_and_group_membership_are_root "${FILENAME}"; then
echo
echo "FINAL RESULT: SUCCESS"
else
echo
echo "FINAL RESULT: FAILURE"
fi
###
###
###
# Test the failure case of the file ownership not being root or the file group membership not being root.
chown nobody "${FILENAME}"
chgrp other "${FILENAME}"
# Display the actual file ownership and group membership.
echo
echo "Test of failure case starting; here's the file being tested:"
ls -l "${FILENAME}"
# Perform the check of ownership being "root" and group membership being "root".
if check_if_ownership_and_group_membership_are_root "${FILENAME}"; then
echo
echo "FINAL RESULT: SUCCESS"
else
echo
echo "FINAL RESULT: FAILURE"
fi
这导致以下输出:
bash-3.2# ./script.sh
Here is what ls will be used:
ls is /usr/bin/ls
Test of success case starting; here's the file being tested:
-rw------- 1 root root 16 Aug 25 13:34 ./test.txt
Part 1: Test of ownership being root supposedly passed
Actual ownership: root
Part 1: Test of group membership being root supposedly passed
Actual group membership: root
FINAL RESULT: SUCCESS
Test of failure case starting; here's the file being tested:
-rw------- 1 nobody other 16 Aug 25 13:34 ./test.txt
Part 1: Test of ownership being root supposedly passed
Actual ownership: nobody
Part 1: Test of group membership being root supposedly passed
Actual group membership: other
FINAL RESULT: SUCCESS
可以看出,我使用 "if" 语句测试的条件总是通过。我做错了什么?
(尽管我希望有人能指导我远离解析 ls,但为了教育起见,无论如何我仍然想知道这个问题的答案。)
在此先感谢所有响应者。
比较运算符两边需要空格 =
:
[[ $(ls -l "${FILENAME}" | awk '{print }') = "root" ]]
另外,当你用双括号[[ ... ]]
.
==
而不是=
一般不推荐依赖ls的输出
if ! [[ $(stat --format '%G' "${FILENAME}") = "root" ]]; then
echo "do the thing"
fi
Shellcheck wiki 讨论了依赖 ls 输出的一些陷阱:https://github.com/koalaman/shellcheck/wiki/SC2012
引用:
ls
is only intended for human consumption: it has a loose, non-standard format and may "clean up" filenames to make output easier to read.