편집: $HOME/.bin이라고 말한 곳에 $HOME/bin을 작성했거나 이와 동등한 내용이 작동해야 했습니다. IE, 사용자의 PATH에 있는 사용자 쓰기 가능 디렉터리.
그래서 API 클라이언트로 배포하는 bash 스크립트가 있습니다. 현재 버전은 다음과 같이 설치됩니다 curl -s http://api.blah.com/install | sudo sh
. 아마도 6개의 서로 다른 패키지 관리 시스템을 처리하여 특정 시점에만 작동하도록 노력할 것입니다 apt-get
. brew install
그러나 지금은 이 솔루션이 여러 시스템에서 작동하기를 원하므로 한 줄을 사용하겠습니다. 그러나 sudo가 전혀 없거나 cygwin이나 심지어 Mac과 같은 시스템에 sudo가 설정되어 있지 않은 사용자도 꽤 많습니다.
시나리오는 사용자가 내 API에 가입하고 신용 카드 정보를 입력하는 것입니다. 참조 구현과 API를 시험해 보거나 명령줄을 사용하여 가상 머신과 Docker 컨테이너를 배포하는 방법으로 사용되는 API용 bash 클라이언트가 있습니다. 사용자가 API 클라이언트를 쉽게 설치할 수 있는 방법을 만들고 싶습니다.
예를 들어, npm은 한 줄 설치였습니다 curl http://npmjs.org/install.sh | sh
. Homebrew에는 한 줄 설치 프로그램도 있습니다 ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
(참조:http://brew.sh).
내 설치 스크립트는 API 클라이언트 스크립트를 다운로드하여 /usr/bin에 저장하고 실행 가능하게 만듭니다. 하지만 sudo 관련 문제와 전역 설치가 실제로 필요하지 않다는 사실을 토대로 사용자의 $HOME/.bin 또는 $HOME/local/bin에 설치하고 싶습니다(기존 파일이 없으면 생성). 동등한).
이것은 내 현재 설치 스크립트입니다.
#!/bin/bash
BASE="https://api.blah.com"
sudo bash -c "curl -s $BASE/mycmd > /usr/bin/mycmd"
sudo chmod uga+x /usr/bin/mycmd
내 첫 번째 생각은 현재 많은 사용자가 zsh를 사용하고 있다는 것입니다. 따라서 $HOME/.bin을 포함하도록 PATH를 업데이트하기 위해 ~/.bashrc에 줄을 추가하거나 수정하면 이러한 시스템에서는 작동하지 않습니다.
그래서 질문을 다시 말씀드리자면,해당 사용자의 PATH($HOME/local/bin 또는 기본적으로 PATH에서 사용할 수 있는 모든 항목)의 사용자 쓰기 가능 디렉터리에 스크립트를 다운로드하고 설치하고 해당 스크립트가 해당 PATH에 있는지 확인하고 요구 사항을 사용하려면 어떤 코드를 사용해야 합니까? (또는 적어도 Unix 프롬프트(sudo 필요 없음)와 같은 것이 있는 경우 거의 모든 사람의 시스템에서 작동할 것이라는 강한 욕구)?
어떤 사람들은 PATH를 수정하는 것이 나쁘다고 생각하기 때문에 특정 경로 디렉터리를 포함하도록 PATH를 자동으로 수정하는 대신 가능하다면 이미 사용자의 PATH에 있는 해당 시스템의 기본 $HOME/whatever/bin에 설치하고 싶습니다.
매우 감사합니다!
답변1
사용자 환경에 자신을 주입하는 프로그램을 가리키는 단어가 있습니다: 바이러스.
간단히 ~/bin/(수동 설치 스크립트에 대한 역사적 사실상 표준) 또는 ~/.local/bin/(루트가 아닌 패키지 관리자가 설치한 스크립트에 대한 최신 준공식 표준)에 설치하면 됩니다. 일반적으로 사용자 친화적인 배포판에는 이미 $PATH에 이들 중 하나 또는 둘 모두가 있습니다.
또는 더 나은 방법은 대화형으로 사용자에게 설치 접두어를 묻는 메시지를 표시하는 것입니다.
답변2
스크립트 자체에서 $PATH를 쿼리하지 않는 이유는 무엇입니까? 사용자의 $PATH(일반적 ~/bin
으로 또는 ~/.local/bin
) 에 쓰기 가능한 디렉터리가 있는지 확인합니다 . 그렇다면 거기에 설치하면 좋을 것입니다. 그렇지 않은 경우 메시지가 표시됩니다. 일부 배포판(예: Ubuntu)에서는 ~/bin
$PATH에 디렉터리가 있으면 자동으로 추가 한다고 생각 하지만 항상 그렇다고 가정할 수는 없습니다.
~/.profile
유일한 옵션은 많은 쉘에서 선택한 디렉토리를 편집하여 $PATH에 설치한 디렉토리를 추가하는 것입니다. 잊어 버리십시오 ~/.bashrc
. bash에만 국한되지 않고 $PATH를 설정할 필요도 없습니다. 그러나 이와 같이 전역 변수를 편집하는 것은 좋은 일이 아닙니다.
가장 좋은 방법은 쓰기 가능한 디렉터리를 확인하고 찾을 수 없으면 메시지를 표시하는 것입니다.
답변3
sh로의 배관은 문제가 있습니다.안전관점에서 좀 더 미묘하게,견고성 및 오류 처리관점.
설치 스크립트에 3줄만 있다면 사용자가 그 3줄만 실행하도록 하면 어떨까요? 그들은 이미 curl
명령을 복사하여 붙여넣고 있습니다. 복사하여 붙여넣는 줄을 조금 더 길게 만들려면 다음을 수행하세요.
mkdir -p ~/bin && curl -s "https://api.blah.com/mycmd" > ~/bin/mycmd && chmod ugo+x ~/bin/mycmd
대부분의 배포판에서는 ~/bin/
디렉터리가 존재하는 한 이 정보가 입력됩니다. 최악의 경우에는 사용자가 자신 의 범위에 해당하지 않더라도 로그 아웃 $PATH
했다가 다시 로그인하여 디렉토리를 추가해야 할 수도 있습니다 . Unix에 능숙하다면 경로에 있는지 확인하고 추가 6자를 제거할 수 있다는 것을 알게 될 것입니다. 그들이 Unix를 처음 접하고 배포판이 도움이 되지 않고 6개의 추가 문자를 입력해야 한다면 아마도 별 문제가 아닐 것입니다.$PATH
$PATH
~/bin/mycmd
mycmd
~/bin/
누군가 루트 액세스 권한이 있고 다른 곳에 설치하려는 경우 ~/bin/
위의 줄을 변경하는 것은 쉽습니다. 변경 방법을 이해하지 못한다면 루트 파일 시스템을 변경해서는 안 됩니다!
답변4
결국 시작하기 페이지에서 두 가지 옵션을 제공했습니다. ~/.local/bin 등을 찾아 ~/.zshrc 또는 ~/.bashrc의 PATH에 추가하는 등 설치 프로그램 스크립트의 기능을 간략하게 설명하겠습니다. 또한 스크립트를 사용하지 않고 수동으로 설치할 수 있는 옵션도 제공하고 간단한 지침도 제공했습니다.
자동 설치 프로그램을 실행하려면 사용자가 다음 명령을 붙여넣고 실행할 수 있습니다.
curl -s https://thesite.com/installmycmd > /tmp/inst; source /tmp/inst
다음은 installmycmd 스크립트입니다.
#!/bin/bash
BASE="https://thesite.com"
declare -a binddirs
bindirs=($HOME/bin $HOME/.local/bin $HOME/.bin)
founddir="false"
findprofile() {
profiles=($HOME/.zshrc $HOME/.bashrc $HOME/.bash_login $HOME/.login $HOME/.profile)
for prof in "${profiles[@]}"; do
if [ -f "$prof" ]; then
echo "$prof"
return
fi
done
touch $HOME/.profile
echo "$HOME/.profile"
}
for bindir in "${bindirs[@]}"; do
if [ -d "$bindir" ]; then
founddir=true
echo "You have a user bin dir here $bindir."
whichprofile=$(findprofile)
pathline=$(grep ^PATH= $whichprofile)
if [[ ! $pathline == *$bindir* ]]; then
echo "Appending $bindir to PATH in $whichprofile"
echo -e "\nexport PATH=\$PATH:$bindir" >> "$whichprofile"
NEWPATH=$PATH:$bindir
export NEWPATH
else
echo "That is in your PATH in $whichprofile"
fi
break;
fi
done
if [ ! -z $NEWPATH ]; then
echo "Exported PATH: $NEWPATH"
export PATH=$NEWPATH
fi
if [[ "$founddir" == "false" ]]; then
echo "Could not find ~/.bin or ~/.local/bin or ~/bin."
echo "Creating ~/.local/bin and adding to PATH"
mkdir -p $HOME/.local/bin
bindir=$HOME/.local/bin
whichprofile=$(findprofile)
echo "Appending PATH edit to $whichprofile"
echo -e "\nexport PATH=$PATH:$HOME/.local/bin" >> "$whichprofile"
export PATH=$PATH:$HOME/.local/bin
fi
bash -c "curl -s $BASE/JSON.sh > $bindir/JSON.sh"
bash -c "curl -s $BASE/mycmd > $bindir/mycmd"
chmod ug+x $bindir/mycmd
chmod ug+x $bindir/JSON.sh