내 목표는 pyenv 및 virtualenv를 통해 로드된 Python 웹 서버 모듈을 편리하게 실행하는 것입니다. 포트 번호에 따라 sudo(1025 미만의 포트 번호)를 사용해야 할 수도 있습니다. 지금까지 ~/.zshrc에 추가한 내용은 다음과 같습니다.
uploadserver() {
if [ $1 = 'end' ]; then
pyenv deactivate uploadserver
elif [ $1 -lt 1025 ]; then
pyenv activate uploadserver
sudo python -m uploadserver $1
elif [ $1 -gt 1024 ]; then
pyenv activate uploadserver
python -m uploadserver $1
else
print "uploadserver <port> <start/end>"
fi
}
sudo가 없으면 내가 원하는 대로 작동합니다. 그러나 sudo의 경우 "sudo: python: 명령을 찾을 수 없습니다"라는 메시지와 함께 실패합니다. 어떻게 작동하게 할 수 있나요? 명령을 수동으로 실행해도 실패하므로 일반적인 스크립팅 문제는 아닌 것 같습니다.
parrot@parrot ~$ uploadserver 80
sudo: python: command not found
(uploadserver) parrot@parrot ~$ uploadserver end
parrot@parrot ~$
가상 환경에서 Python의 전체 경로를 추가하더라도 sudo 호출이 실패합니다.
(uploadserver) parrot@parrot ~$ sudo /home/parrot/.pyenv/shims/python
pyenv: python: 명령을 찾을 수 없습니다
업데이트 1 나는 올바른 해결책을 찾은 것 같아요. 스크립트의 sudo 호출을 아래 호출로 바꾸면 작동합니다. 이것이 올바른 해결책인지 모르겠습니다.
$ sudo -E env PATH=${PATH} python -m uploadserver $1
업데이트 2 Gilles의 조언 "그러니 악한 짓은 그만하세요"를 읽은 후 Python 실행 파일에 대해 CAP_NET_BIND_SERVICE 옵션을 설정하기로 결정했습니다. 이는 다른 사용자에게도 적합한 솔루션이 아닐 수 있지만 제 사용 사례에서는 이렇게 처리해도 괜찮다고 생각합니다. 작동하려면 다음 명령을 실행해야했습니다.
parrot@parrot ~$ sudo setcap 'cap_net_bind_service=+ep' /home/parrot/.pyenv/versions/3.12.2/bin/python3.12
Python의 pyenv는 단지 래퍼일 뿐이므로 이 파일에 대한 기능 설정은 효과가 없습니다.
(uploadserver) parrot@parrot ~$ which python
/home/parrot/.pyenv/shims/python
(uploadserver) parrot@parrot ~$ getcap /home/parrot/.pyenv/shims/python
/home/parrot/.pyenv/shims/python cap_net_bind_service=ep
(uploadserver) parrot@parrot ~$ python -m uploadserver 80
...
PermissionError: [Errno 13] Permission denied
답변1
Sudo는 대부분의 환경 변수를 제거합니다(또는 그 중 일부를 "안전한" 기본값으로 재설정합니다 PATH
). 이는 특정 환경 변수가 있는 경우 명령이 예상치 못한 방식으로 작동하여 호출자가 의도한 것보다 더 많은 작업을 수행할 수 있기 때문에 sudo 규칙이 특정 명령에 대한 액세스 권한을 부여할 때 필요합니다. 예를 들어 LD_PRELOAD
호출자가 상승된 권한으로 임의 코드를 실행할 수 있도록 허용합니다. PYTHONPATH
명령이 Python 프로그램인 경우에도 마찬가지입니다.
sudo 규칙이 대상 사용자로서 임의 명령 실행을 허용하는 특정 경우에는 이 보안 기능이 필요하지 않습니다. 그러나 sudo는 이 기능을 기본적으로 완화하지 않습니다. 왜냐하면 수행하기가 더 어렵고 관리자가 실수하기 쉽기 때문입니다.
--preserve-env
sudo 규칙이 허용하는 경우 ( )를 사용하여 거의 모든 환경 변수를 유지하도록 지시하거나 -E
특정 변수를 설정할 수 있습니다( sudo FOO=bar mycommand
기능적으로 동일함 sudo env FOO=bar mycommand
). 그런 다음 실행할 수 있습니다 sudo PATH="$PATH" python …
.
그러나 이는 프로그램을 루트로 시작하므로 좋지 않은 생각입니다. 권한 있는 포트를 연 후 Python 스크립트를 사용하여 권한을 올바르게 제거합니다. 또한 명령줄 및 구성 파일을 구문 분석할 때와 같이 권한을 포기하기 전에 예상치 못한 작업을 수행하지 않는 것에 의존합니다.
sudo 대신 (1) 포트를 열고 (2) (3) 서버 프로그램을 실행하기 전에 권한을 제거하도록 설계된 도구를 사용하십시오. 이것은 될 수있다tcpd
,시스템화된 동등물,승인 바인딩또는 다른 많은 가능성 중 하나1 2.