在Bash Shell脚本中检查常规文件和目录所有权和组成员身份

时间:2016-08-25 13:58:14

标签: bash shell scripting solaris

我正在Bash 3.2.57(1)中编写shell脚本 - 在Solaris 10下发布 - uname -a yield" SunOS hostname 5.10 Generic_150400-35 sun4v sparc sun4v")。

我试图解决的最终问题是,在bash shell脚本中,确定常规文件或目录的所有者和组成员身份。

很遗憾,我无法使用统计数据。

如果stat不可用,我知道的下一个最好的事情就是解析ls -l输出中的所有者和组成员资格。我不喜欢这种方法,以防可移植性成为一个问题,如果我遇到过带有特殊字符的文件名,它会抛出解析。但是,解析ls -l的输出是我目前得到的......

这导致两个问题。

问题一

缺少统计排除ls -l <​​/ strong>的条件作为解决方案的一部分时,是否有一种被接受的,不太过黑的方式来确定我的特定平台上的常规文件或目录的所有者和组成员身份(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="${1}"

   # Check ownership of "${FILENAME}".
   if [[ $(ls -l "${FILENAME}" | awk '{print $3}')="root" ]]; then
      echo
      echo "Part 1: Test of ownership being root supposedly passed"
      echo "Actual ownership: " $(ls -l "${FILENAME}" | awk '{print $3}')

      # 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 $3}')

      # 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 $4}')="root" ]]; then
      echo
      echo "Part 1: Test of group membership being root supposedly passed"
      echo "Actual group membership: " $(ls -l "${FILENAME}" | awk '{print $4}')

      # 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 $4}')

      # 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

可以看出,我使用&#34; if&#34;进行测试的条件。陈述总是通过。我做错了什么?

(即使我希望有人可以引导我远离解析ls,但我仍然希望在任何情况下都知道这个问题的答案是出于教育的原因。)

真诚地感谢所有响应者。

2 个答案:

答案 0 :(得分:2)

比较运算符=周围需要空格:

[[ $(ls -l "${FILENAME}" | awk '{print $4}') = "root" ]]

此外,当您使用双括号==编写条件时,应使用=代替[[ ... ]]

答案 1 :(得分:0)

一般不推荐依赖ls的输出

if ! [[ $(stat --format '%G' "${FILENAME}") = "root" ]]; then
    echo "do the thing"
fi

Shellcheck wiki 讨论了依赖 ls 输出的一些陷阱:https://github.com/koalaman/shellcheck/wiki/SC2012

引用:

<块引用>

ls 仅供人类食用:它具有松散、 非标准格式,可能会“清理”文件名以使输出更容易 阅读。