sudo로 명령을 실행하고 sudo 권한이 시간 초과될 때만 텍스트 줄을 에코하는 스크립트를 작성 중입니다. 따라서 sudo로 명령을 실행하려면 사용자(루트 아님)가 비밀번호를 다시 입력해야 합니다.
이를 어떻게 확인하나요? sudo로 실행 해도 $(id -u)
현재 사용자 ID가 반환되므로 0과 일치하는지 확인할 방법이 없습니다.
조용히 확인할 방법이 필요해요.
답변1
-n
다음의 권한이 아직 있는지 확인하려면 이 옵션을 사용하세요 man sudo
.
-N,--비대화형
사용자에게 어떤 유형의 입력도 요청하지 마세요. 명령을 실행하는 데 비밀번호가 필요한 경우 sudo는 오류 메시지를 표시하고 종료됩니다.
예를 들어,
sudo -n true 2>/dev/null && echo Privileges active || echo Privileges inactive
sudo -n true
확인 후 실제 사용 사이에 권한이 만료될 수 있습니다. 직접 시도해보고 sudo -n command...
실패할 경우 메시지를 표시하고 sudo
대화형으로 다시 실행해 볼 수도 있습니다.
편집: 아래 ruakh의 의견도 참조하세요.
답변2
달리기:
sudo -nv
sudo 권한이 만료된 경우 종료 코드 1로 종료되고 다음이 출력됩니다.
sudo: a password is required
유효한 캐시된 자격 증명이 있는 경우 이 명령은 성공하고 아무것도 출력하지 않습니다.
모든 것을 종합하면 다음과 같은 스크립트가 있습니다.아무 말 않고유효한 캐시된 자격 증명이 있는지 확인하세요.
if sudo -nv 2>/dev/null; then
echo "no sudo password required"
else
echo "sudo password expired"
fi
다른 답변/댓글에서 언급했듯이 -v
sudo의 옵션("인증")은 캐시된 자격 증명을 생성하기 위한 인증 프롬프트가 있는 경우 캐시된 자격 증명을 자동으로 업데이트하고 -n
옵션("비대화형")은 sudo가 다음과 같은 대화형 프롬프트를 생성하는 것을 방지합니다. 인증 프롬프트로.
답변3
sudo -nv
잘 작동하지만 sudo 오류 및 pam 인증 메시지로 시스템 로그를 오염시킵니다. sudo 권한에 대한 bash 프롬프트를 확인해야 하므로 매우 자주 실행되고 내 로그에는 거의 이러한 소음만 포함됩니다.
sudo 타임스탬프 파일을 직접 구문 분석하는 것이 가능합니다. 이를 위해 작은 C 유틸리티를 작성했습니다.
/* compile and set permissions: */
/* $ gcc checksudo.c -o checksudo -std=gnu99 -O2 */
/* $ chown root:root checksudo */
/* $ chmod +s checksudo */
#define USERNAME "replace-with-your-username"
#define TIMEOUT 5
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>
void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result) {
if ((stop->tv_nsec - start->tv_nsec) < 0) {
result->tv_sec = stop->tv_sec - start->tv_sec - 1;
result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
} else {
result->tv_sec = stop->tv_sec - start->tv_sec;
result->tv_nsec = stop->tv_nsec - start->tv_nsec;
}
return;
}
int main(int argc, char** argv) {
if (geteuid() != 0) {
printf("uid is not 0 - checksudo must be owned by uid 0 and have the setuid bit set\n");
return 2;
}
struct timespec current_time;
if (clock_gettime(CLOCK_BOOTTIME, ¤t_time) != 0) {
printf("Unable to get current time: %s\n", strerror(errno));
return 2;
}
struct stat ttypath_stat;
if (stat(ttyname(0), &ttypath_stat) != 0) {
printf("Unable to stat current tty: %s\n", strerror(errno));
return 2;
}
FILE* timestamp_fd = fopen("/var/run/sudo/ts/" USERNAME, "rb");
if (timestamp_fd == NULL) {
printf("Unable to open sudo timestamp file: %s\n", strerror(errno));
return 2;
}
long offset = 0;
int found = 0;
while (1) {
if (fseek(timestamp_fd, offset, SEEK_SET) != 0) {
printf("Failed to seek timestamp file: %s\n", strerror(errno));
return 2;
}
unsigned short timestamp_entry_header[4];
if (feof(timestamp_fd)) {
printf("matching timestamp not found\n");
return 2;
}
if (fread(×tamp_entry_header, sizeof(unsigned short), 4, timestamp_fd) < 4) {
break;
}
if (ferror(timestamp_fd)) {
printf("IO error when reading timestamp file\n");
return 2;
}
// read tty device id
if (timestamp_entry_header[2] == 2 && timestamp_entry_header[3] == 0) {
if (fseek(timestamp_fd, offset + 32, SEEK_SET) != 0) {
printf("Failed to seek timestamp file: %s\n", strerror(errno));
return 2;
}
dev_t tty_dev_id;
if (fread(&tty_dev_id, sizeof(dev_t), 1, timestamp_fd) < 1) {
printf("EOF when reading tty device id\n");
return 2;
}
if (tty_dev_id == ttypath_stat.st_rdev) {
// read timestamp
if (fseek(timestamp_fd, offset + 16, SEEK_SET) != 0) {
printf("Failed to seek timestamp file: %s\n", strerror(errno));
return 2;
}
struct timespec sudo_time;
if (fread(&sudo_time, sizeof(struct timespec), 1, timestamp_fd) < 1) {
printf("EOF when reading timestamp\n");
return 2;
}
struct timespec time_since_sudo;
timespec_diff(&sudo_time, ¤t_time, &time_since_sudo);
found = time_since_sudo.tv_sec < TIMEOUT * 60;
break;
}
}
offset += timestamp_entry_header[1];
}
fclose(timestamp_fd);
return !found;
}