Не бесконечный цикл, но лучший способ найти фактический предел даты:
#!/bin/bash
j=$((1<<61))
i=0
while ((j>0)); do
if date +'%Y-%m-%d' -d "$((i+j)) days ago" >/dev/null 2>&1; then
((i+=j)) ; # printf 'running i %d 0x%x\n' "$i"{,}
else
((j>>=1)); # printf 'new j %d 0x%x\n' "$j"{,}
fi
((k++))
# ((k%10)) || printf 'still running %d 0x%x %d %d' "$i"{,} "$j" "$k"
done
printf "final value of limit %d 0x%x in %d loops\n" "$i"{,} "$k"
Таким образом, предел даты будет:
final value of limit 2147483649 0x80000001 in 64 loops
Удалите символ комментария # , чтобы увидеть, как это делается.
Это похоже на 32-битное число:
$ printf '%d\n%d\n' "$(( (1<<31) + 1 ))" "0x80000001"
2147483649
2147483649
Фактически, это 2 ** 31 + номер дня месяца.
Если мы попробуем с последним днем декабря (измените строку 5 в сценарии выше):
date +'%Y-%m-%d' -d "2017-12-31 $((i+j)) days ago"
Мы получим:
final value of limit 2147483679 0x8000001f in 68 loops
Это 31 выше 2 ** 31
:
$ printf '%d\n%d\n' "$(( (2**31) + 31 ))" "0x8000001f"
2147483679
2147483679
Максимальное значение для целого числа оболочки - i меньше 2, увеличенное до 63:
$ echo $(( (2**63) - 1 ))
9223372036854775807
Мы можем получить десятичное и шестнадцатеричное представление следующим образом:
$ printf '%d %x\n' "$(( (2**63) - 1 ))"{,}
9223372036854775807 7fffffffffffffff
Это максимальное число, представимое в виде целого числа со знаком 64 бита (если ваша система, конечно, 64 бита). Следующее число (просто добавьте один) будет обернуто (переполнено) до отрицательного числа:
$ echo $(( (2**63) ))
-9223372036854775808
$ printf '%d %x\n' "$(( (2**63) ))"{,}
-9223372036854775808 8000000000000000
Это самое отрицательное число для 64-битного целого числа со знаком.
Но более быстрый способ получить тот же результат - использовать сдвиг влево, который делает то же самое, что и умножение числа на два:
$ printf '%d %x\n' "$(( (1<<63) - 1 ))"{,}
9223372036854775807 7fffffffffffffff
У меня был некоторый успех в этом - если не с контейнером lxc, то мне удалось заставить его работать для частного пространства имен монтирования. Поскольку lxc построен на базовых пространствах имен linux, которые я также использовал, я не вижу причин, почему это не должно работать у вас.
В первую очередь я настроил пространство имен следующим образом:
sudo unshare -m sh -c '
mount -ttmpfs none /tmp
echo x > /tmp/mytmp
findmnt -o+PROPAGATION /tmp
echo "$$"
cd /tmp
exec "$0" -i
TARGET SOURCE FSTYPE OPTIONS PROPAGATION
/tmp tmpfs tmpfs rw private
/tmp none tmpfs rw,relatime private
29384
$
... и получил интерактивную оболочку. Следующее, что я сделал в отдельной терминальной сессии...
sudo sh -c ' { cd /dev/fd/0 ; mkdir mnt
ls -l; cat mytmp
} 3<$0/ns/mnt <$0/29384/cwd
' /proc/29384
drwxr-xr-x 2 root root 40 Jan 4 02:52 mnt
-rw-r--r-- 1 root root 2 Jan 4 02:38 mytmp
x
... что было очень обнадеживающе!
Но я не смог выполнить монтирование - каждый раз, когда я пытался смонтировать
родительский ns каталог поверх одного из дочерних ns, он терпел неудачу. Некоторые исследования показывают, что это сделано специально (в частности: см. предостережения в man 7 user_namespaces
относительно флагов PROPAGATION). Что сработало, так это (в новом пространстве имен):
sudo unshare --propagation slave -m sh -c '
mount -ttmpfs none /tmp; cd /tmp
exec "$0" -i'
А затем в сессии родительского пространства имен...
sudo mount --bind / /mnt
sudo mount --bind / /tmp
sudo mount --bind /tmp /mnt/img/tmp
Теперь вышеописанное работает в первом случае, но не во втором. Поскольку дочернее ns не распространяет изменения fs вверх, родительское не повлияет на изменения, внесенные в его представление fs. И так как у дочернего ns есть собственное монтирование на /tmp
, все, что делает родитель, не имеет значения. Однако, если существует некоторая общая иерархия и дочерний ns настроен на получение изменений файловой системы, то он будет видеть изменения, которые родитель распространяет вниз.
В дочернем ns после выполнения вышеуказанного...
ls /tmp /mnt /mnt/tmp
/mnt:
bin dev etc lib mnt proc run srv tmp var
boot esp home lib64 opt root sbin sys usr
/mnt/tmp:
serverauth.FT3Z6IFyWW
systemd-private-...systemd-timesyncd.service-YUkVU6
/tmp:
И так, я полагаю, чтобы ответить на вопрос - да, я считаю, что это возможно. Но я также уверен, что вам потребуется организовать это заранее.