Que código devo usar para baixar e instalar meu script em um diretório gravável pelo usuário no PATH do usuário (sem exigir o sudo)?

1

Edit: lugares onde eu disse $ HOME / .bin eu deveria ter escrito $ HOME / bin ou qualquer equivalente está bem. I.E, qualquer diretório gravável pelo usuário que esteja no PATH do usuário.

Portanto, tenho um script bash que estou distribuindo como um cliente para minha API. A versão atual é instalada assim curl -s http://api.blah.com/install | sudo sh . Eu posso tentar lidar com seis sistemas de gerenciamento de pacotes diferentes para que eles possam apenas apt-get ou brew install em algum momento, mas por enquanto eu vou com o one-liner já que eu quero que esta solução funcione para múltiplos sistemas. No entanto, aparentemente existem alguns usuários em sistemas como o cygwin ou até mesmo Macs que não têm sudo ou não o configuram.

O cenário é um usuário se inscrever para minha API, insere as informações do cartão de crédito. Eu tenho um cliente bash para a API que também serve como uma implementação de referência e também uma maneira de testar a API ou implantar contêineres de VMs e Docker usando a linha de comando. Eu quero criar uma maneira fácil para os usuários instalarem o cliente da API.

Por exemplo, costumava haver uma instalação de uma linha para npm curl http://npmjs.org/install.sh | sh . O homebrew também tem um instalador de uma linha ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)" (veja link ).

Meu script de instalação apenas faz o download do script do cliente API e o coloca em / usr / bin e o torna executável. Mas eu estou pensando com base nos problemas com o sudo eo fato de que isso realmente não precisa ser instalado globalmente, gostaria de instalá-lo no $ HOME / .bin ou $ HOME / local / bin do usuário (criar esse se não houver equivalente existente).

Este é o meu script de instalação atual:

#!/bin/bash
BASE="https://api.blah.com"

sudo bash -c "curl -s $BASE/mycmd > /usr/bin/mycmd"
sudo chmod uga+x /usr/bin/mycmd

Primeira ruga que me ocorre é que muitos usuários estão agora em zsh. Portanto, se eu adicionar ou modificar uma linha em ~ / .bashrc que atualize o PATH para incluir $ HOME / .bin, isso não funcionará para esses sistemas.

Então, para reafirmar a pergunta, qual código devo usar para baixar e instalar meu script em um diretório gravável pelo usuário no PATH desse usuário ($ HOME / local / bin ou o que estiver disponível no PATH por padrão) diretório e certifique-se de que está em seu PATH, com o requisito (ou pelo menos strong desejo) de que isso funcionará no sistema de quase todos (se eles tiverem algo como um prompt Unix) (sem exigir sudo)?

Como algumas pessoas consideram modificar o PATH como malvado, gostaria de instalar no padrão $ HOME / whatever / bin para esse sistema, que já está no PATH do usuário, se possível, em vez de modificar automaticamente seu PATH para incluir algum diretório particular.

Muito obrigado!

    
por Jason Livesay 25.05.2014 / 07:19

4 respostas

0

Acabei dando a eles duas opções na minha página "Primeiros passos". Eu explico brevemente o que o script do instalador faz, como procurar por ~ / .local / bin ou algo assim e, em seguida, potencialmente adicionando isso ao PATH em ~ / .zshrc ou ~ / .bashrc. Eu também lhes dou a opção de instalar manualmente, em vez de usar o script, com instruções simples para fazer isso.

Para executar o instalador automático, o usuário deve colar e executar um comando como este:

curl -s https://thesite.com/installmycmd > /tmp/inst; source /tmp/inst

Este é o script 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
    
por 02.06.2014 / 17:13
4

Existe uma palavra para programas que se injetam no ambiente do usuário: vírus.

Basta instalar em ~ / bin / (o padrão histórico de fato para scripts instalados manualmente) ou ~ / .local / bin / (o padrão moderno, quase-normal para scripts instalados por um gerenciador de pacotes não-raiz). Normalmente, as distros user-friendly já terão um ou ambos em $ PATH.

Ou melhor ainda, interativamente, solicite ao usuário o prefixo de instalação.

    
por 25.05.2014 / 08:51
2

Por que você não consulta o $ PATH no próprio script? Verifique se o usuário possui algum diretório em seu $ PATH para o qual ele pode gravar (geralmente, ~/bin ou ~/.local/bin ). Se o fizerem, ótimo, instale lá. Se não, você avisa. Acredito que algumas distribuições, como o Ubuntu, adicionarão ~/bin ao $ PATH automaticamente se o diretório existir, mas você não pode presumir que sempre seja o caso.

A única outra opção que você tem é adicionar o diretório que você instalou no $ PATH editando ~/.profile , que é originado por muitos shells. Esqueça ~/.bashrc , não só é bash específico, mas o $ PATH não tem nenhum negócio sendo definido lá em primeiro lugar. No entanto, editar variáveis globais como essa não é uma coisa muito boa para se fazer.

A melhor coisa é verificar se há diretórios graváveis e perguntar se nenhum foi encontrado.

    
por 25.05.2014 / 18:03
2

Pipar para sh é questionável, de um segurança do ponto de vista, e mais sutilmente, um robustez e tratamento de erros ponto de vista.

Se o seu script de instalação tiver apenas 3 linhas, por que o usuário não executou apenas essas 3 linhas? Eles já estão copiando e colando seu comando curl , e fazer a linha que eles copiam e colam um pouco mais permitiria que você fizesse:

mkdir -p ~/bin && curl -s "https://api.blah.com/mycmd" > ~/bin/mycmd && chmod ugo+x ~/bin/mycmd

Na maioria das distros, ~/bin/ é colocado em $PATH , contanto que o diretório exista. Na pior das hipóteses, os usuários podem precisar fazer logout e voltar para obter o diretório adicionado ao $PATH . Mesmo que não esteja no $PATH , você pode instruir as pessoas a executar apenas ~/bin/mycmd em vez de mycmd . Se eles forem bastante experientes em Unix, eles saberão que podem garantir que ~/bin/ esteja em seu caminho e descartem os 6 caracteres extras. Se eles não são experientes em Unix, e sua distribuição é inútil, eles precisam digitar 6 caracteres extras - provavelmente não é grande coisa.

E se alguém tiver raiz e quiser instalar algo diferente de ~/bin/ , será fácil alterar a linha acima para isso - e se eles não entenderem como fazer essa alteração, eles não devem alterar o sistema de arquivos raiz!

    
por 25.05.2014 / 18:57