Linux Permission denied: 파일보다 실행 계정과 경로부터

셸에서 파일이 보이는데 서비스가 Permission denied로 실패하면, 먼저 실패한 동작이 읽기·쓰기·실행 중 무엇인지 확인합니다. SSH 로그인 계정의 성공은 PHP-FPM이나 systemd 서비스 계정의 접근 권한을 증명하지 않습니다.

읽을 수 있는 스크립트도 직접 실행은 실패할 수 있다

일반 사용자 소유의 임시 셸 스크립트를 0600으로 두고 직접 실행했을 때 Python subprocess는 PermissionError를 반환했습니다. 같은 파일을 0700으로 바꾸면 종료 코드 0이었습니다. 내용·경로·실행 계정을 고정하고 실행 비트만 바꾼 결과입니다. 인터프리터로 파일을 읽어 실행하는 방식과 파일 자체를 exec하는 방식은 같은 검사가 아닙니다.

id
namei -l /srv/example/bin/task
stat -c '%U %G %a %n' /srv/example/bin/task
findmnt -T /srv/example/bin/task -o TARGET,OPTIONS

예시 경로를 실제 대상 경로로 바꾸고 서비스가 쓰는 계정·그룹과 비교합니다. namei로 모든 부모 디렉터리의 탐색 권한을 확인하고, findmnt로 noexec·읽기 전용 같은 마운트 조건을 구분합니다. 부모 디렉터리에 탐색 권한이 없으면 최종 파일의 권한이 충분해도 접근에 실패할 수 있습니다. Linux 경로 해석이 이 규칙을 설명합니다.

한 권한을 고친 뒤 같은 계정으로 재검사

소유권·그룹·ACL 중 실제로 틀린 한 항목만 수정합니다. 전체 트리에 chmod 777이나 chown -R을 적용하면 공유 데이터와 키 파일까지 바뀔 수 있습니다. 기본 권한이 맞으면 서비스의 읽기 전용 경로 설정, AppArmor·SELinux 거부 기록, 스크립트 첫 줄의 인터프리터 경로를 확인합니다. 설정 파일에 적힌 계정과 실제 프로세스 계정이 같은지도 대조하세요.

검증은 같은 실행 계정·같은 경로·같은 동작으로 수행해야 합니다. 쓰기 확인이 필요하면 승인된 테스트 디렉터리에 고유한 임시 파일을 만들고 그 파일만 지웁니다. 이번 실행 비트 실험은 모든 Permission denied 원인의 재현이나 운영 서비스 복구 검사가 아닙니다.