Почему я не могу установить дату своих машин GNU/Linux на Эпоху?

Исправьте назначения массивов и измените тест на регулярное выражение.

#!/bin/bash

FNAME="JACK"
LNAME="BLACK"

SEARCHNAME=()
SEARCHNAME+=("JACK-BLACK")
SEARCHNAME+=("JOHN-JAMES")
SEARCHNAME+=("CHRIS-TOPHER")
SEARCHNAME+=("JEN-NAY")

NAME="${FNAME}-${LNAME}"

if [[ "${SEARCHNAME[@]}" =~ $NAME ]]; then
    echo "PASSED"
else
    echo "FAILED"
fi

echo "SEARCH IN: ${SEARCHNAME[@]}"
echo "FOR NAME: ${NAME}"
2
02.08.2019, 12:35
2 ответа

Я не могу точно воспроизвести «Неверный аргумент» для той эпохи в более старой системе, но:

# strace date -s '@-1'
…
clock_settime(CLOCK_REALTIME, {4294967295, 0}) = -1 EINVAL (Invalid argument)
settimeofday({4294967295, 0}, NULL)     = -1 EINVAL (Invalid argument)
write(2, "date: ", 6date: )                   = 6
write(2, "cannot set date", 15cannot set date)         = 15
write(2, ": Invalid argument", 18: Invalid argument)      = 18
write(2, "\n", 1

(А затем dateпродолжает отображать дату, которую он хотел установить, хотя на самом деле он ее не установил.)

Проще говоря, dateвызывает ядро, чтобы установить дату на одну секунду раньше эпохи, и ядро ​​сообщает ему, что предложенная дата недействительна.

Теперь в приведенной выше трассировке вы видите 4294967295 как количество секунд вместо -1. Это число равно 2^32 -1, и я запускал его на 32-битной -машине. Это на самом деле не источник проблемы :это проблема отображения в strace, которая не знает, должно ли значение быть подписанным или нет. На самом деле количество секунд — это целое число со знаком типа time_t. Glibc 2.23 в Linux определяет time_tкак __time_tв /usr/include/time.h, __time_tкак __TIME_T_TYPEв/usr/include/bits/types.h__TIME_T_TYPEкак __SYSCALL_SLONG_TYPE, что равно __SQUAD_TYPEв /usr/include/bits/typesizes.h, и __SQUAD_TYPEкак 64 -тип битового знака в /usr/include/bits/types.h. На стороне ядра, начиная с 4.4,определение типа аргумента вызова settimeofday— это либо struct timespec, где секунды — это __kernel_time_t, который является 64-разрядным -битным типом со знаком на 64-битных -машинах, либоtime64_tкоторый является подписанным 64-битным -типом на 32-битных -машинах. Таким образом, ядро ​​видит -1 как -1, а не какое-то большое положительное число.

Причина, по которой вы не можете вернуться в предыдущую эпоху, заключается в том, что ядро ​​Linux явно отказывается это делать. Системный вызовsettimeofdayвозвращает EINVAL («Недопустимый аргумент» ), еслиtimeval_validотклоняет заданную временную структуру, а эта функция отклоняет отрицательное число секунд.

В разных версиях ядра код организован по-разному, но я не думаю, что поведение изменилось.

Я не видел причин, по которым время, равное 0, было бы отклонено, и это работало на виртуальной машине, где я тестировал это.

Причина для проверки работоспособности, по-видимому, заключается в том, что существует код, который хранит время, прошедшее с начала эпохи, как целое число без знака, и, таким образом, не может справиться с датами, предшествующими эпохе. Некоторый код может интерпретировать 0 как «дата неизвестна», поэтому имеет смысл отклонить и 0, но на самом деле Linux этого не делает, и в любом случае это будет длиться всего секунду.

Времена, предшествующие эпохе, несомненно, могут быть представлены и ими можно манипулировать. Многим программам необходимо отслеживать время прошлых событий. База данных часовых поясов, которую использует практически каждая операционная система, содержит исторические данные, начиная с того времени, когда часовые пояса были кодифицированы (примерно в то время, когда железные дороги начали развиваться ). Но вы не можете сказать Linux-компьютеру, что текущее время до 1970 года.

4
27.01.2020, 21:55

Это может произойти, если представление об эпохе текущего часового пояса предшествует (UTC )эпохе Unix. Такие времена просто не могут быть представлены.

1
27.01.2020, 21:55

Теги

Похожие вопросы