1

Как мы можем написать скрипт вокруг dscl, чтобы перебрать используемые в настоящий момент идентификаторы, перечисленные в списке, а затем выдать первый идентификатор под 500, который еще не используется?

Обновление № 1 (17 февраля 2013 г.)

Я нашел несколько очень полезных сценариев на http://wiki.awkwardtv.org/wiki/Manage_users_and_groups_scripts, которые я смог набрать до такой степени, что я мог получить первый доступный идентификатор выше заданного числа, но у меня все еще нет способ написания сценариев, чтобы перестать смотреть за пределы определенного верхнего предела, например, 500.

#!/bin/sh
continue="no"
number_used="dontknow"
fnumber=300
user_id=0
until [ $continue = "yes" ] ; do
  if [ `dscl . -list /Users UniqueID | awk '{print $2, "\t", $1}' | sort -ug | grep -c "$fnumber"` -gt 0 ] ; then
    number_used=true
  else
    number_used=false
  fi
  if [ $number_used = "true" ] ; then
    fnumber=`expr $fnumber + 1`
  else
    user_id="$fnumber"
    continue="yes"
  fi
done;
echo "Next available user_id: $user_id"

Обновление № 2 (17 февраля 2013 г.)

Я полагаю, что мог бы работать в обратном направлении, но все же, что, если каждый идентификатор пользователя от 500 до 0 взят? Мне все еще нужно установить нижнюю границу, чтобы выйти из грязной ситуации с отрицательным идентификатором.

#!/bin/sh
continue="no"
number_used="dontknow"
fnumber_work_backwards_from=500
fnumber=$fnumber_work_backwards_from
user_id=0
until [ $continue = "yes" ] ; do
  if [ `dscl . -list /Users UniqueID | awk '{print $2, "\t", $1}' | sort -ug | grep -c "$fnumber"` -gt 0 ] ; then
    number_used=true
  else
    number_used=false
  fi
  if [ $number_used = "true" ] ; then
    fnumber=`expr $fnumber - 1`
  else
    user_id="$fnumber"
    continue="yes"
  fi
done;
echo "First available user_id which is closest to and lower than $fnumber_work_backwards_from: $user_id"

2 ответа2

0

Это должно работать, чтобы найти то, что вам нужно. Функция find_next_userid ниже будет искать между двумя числами включительно, чтобы найти первый неиспользуемый идентификатор пользователя. Для вашего случая просто используйте 0 и 499 , как показано ниже. Функция возвращает пустую строку, если не может найти пустых слотов, поэтому вам необходимо проверить это перед использованием значения echo (как показано ниже).

Я понимаю, что это не использует dscl, но это должно работать и быть более переносимым. [Обновление: добавлена версия с использованием dscl.]

Технически я использую bash, поэтому я заметил это; Я не уверен, будет ли работать в ш или нет.

Протестировано на OS X 10.9.4.

#!/bin/bash
user_exists()
{
    username=$1

    if id -u $username >/dev/null 2>&1; then
        return 0
    else
        return -1
    fi
}

user_exists_dscl()
{
    username=$1

    user_found=`dscl . -search /Users UniqueID $username | awk 'FNR == 2 {print $1}'`
    if [ "${user_found}" != "" ] ; then
        return 0
    else
        return -1
    fi
}

find_next_userid()
{
    low=$1
    hi=$2

    for curr in `seq $low $hi`;
    do
        if ! (user_exists $curr) ; then
            echo $curr
            break
        fi
    done

    echo ""
}

FIRST_UNUSED_USERID=`find_next_userid 0 499`

if [ "$FIRST_UNUSED_USERID" != "" ]; then
    echo "Do your stuff here!"
else
    echo "No unused userid found!"
fi

Изменить: Забыл включить user_exists() . Обновлено, чтобы отметить, что это решение не использует dscl, но все еще работает. Я думаю, что у меня может быть решение с помощью DSCL в ближайшее время.

Редактировать 2: добавлен user_exists_dscl . Замените вызовы user_exists на user_exists_dscl если вам действительно нужно использовать dscl вместо id .

0

Это может быть сделано, например, с Ruby, который гораздо более лаконичен, чем любой скрипт Bash, который вы могли бы найти для этого.

dscl . -list /Users UniqueID | awk '{print $2}' | 
ruby -e 'puts ((0..500).to_a - STDIN.readlines.map(&:to_i)).first'

Мы просто вычитаем фактические идентификаторы (в виде массива) из другого массива, состоящего из чисел от 0 до 500. Это дает нам все неиспользуемые идентификаторы в массиве, и отсюда мы берем первый, поскольку он уже отсортирован.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .