Script de pos instalação, sugestões e correções

Não achei a declaração da variável “SUDO_USER”.
Use o software “shellcheck” para fazer a revisão automática do seu código.
Depois que você corrigir os erros que o shellcheck indicar você passa a fazer revisão manual.


Os vermelhos são erros graves, o amarelo requer atenção e o verde geralmente da para ignorar mas nos meus códigos eu costumo a arrumar os verdes tmb.
No final o shellcheck da o link das paginas de uma explicação e exemplo do código correto a se usar.

Exemplo o erro “SC2144” que esta ai na imagem ele coloco no final o link desta pagina: SC2144 · koalaman/shellcheck Wiki · GitHub

Se você seguir todas as indicação do shellcheck seu script vai ficar mais próximo de um script profissional.

4 curtidas

Interessante. Gostei.
Eu estou criando um aplicativo para personalização de distros Debian-like em Python . Por enquanto ainda estou em fase de testes e depois de tudo OK, vou criar a interface gráfica.

Muito interessante esse shellcheck , assim que tiver tempo vou revisar usando esse programa.


SUDO_USER é uma variável de ambiente do sistema, disponível quando se roda o script como sudo:
https://www.sudo.ws/man/sudo.man.html#SUDO_USER

Como eu uso um script só para fazer tudo, eu preciso de permissão de superusuário para instalar os programas, mas para fazer as configurações eu tenho que fazer como usuário local. Por essa razão preciso usar SUDO_USER dentro de um comando sudo, seria o nome do usuário atual.

Olhando melhor a imagem que vc postou. O programa aponta erro amarelo sc2027. Mas ao mesmo tempo aponta erro verde sc2086 e pede para colocar aspas duplas.
Ficou confuso. Será que é melhor deixar com aspas duplas em todas as variáveis para evitar erros quando o valor da variável tiver mais de uma palavra?, ex: “Área de Trabalho”

Se eu usar assim será que é errado?

“\033[01;33m**** Adicionando PPA: $ppa\033[0m”

Assim achei muito confuso:

“\033[01;33m**** Adicionando PPA: “”$ppa”"\033[0m"

É como o shellcheck indico a forma correta.
Eu não sei em que tipo de senário isso causa problema, mas é amarelo requer atenção.

“\033[01;33m**** Adicionando PPA: $ppa\033[0m”
Esta correto, olha o exemplo da pagina do wiki do shellcheck.

Problematic code:

echo "You enter "$HOSTNAME". You can smell the wumpus." >> /etc/issue

Correct code:

echo "You enter $HOSTNAME. You can smell the wumpus." >> /etc/issue

As variáveis devem ficar entre aspas duplas.
Mas no seu script você coloco a variável $ppa fora das aspas duplas.
echo -e "\033[01;33m**** Adicionando PPA: \033[01;36m"$ppa"\033[0m"Isso que você fez não é uma boa pratica.

1 curtida

Existe também uma versão online do shellcheck.
Mas ele esta no repositório do Lubuntu por isso é provável ele estar no repositório do Mint tmb.

1 curtida

Você tá causando conflito no parser por causa da forma como você chama a variável, o ideal é sempre chavear elas:

# Ao invés de:

echo "$ppa"

# Use:

echo "${ppa}"

Fiz algumas correções, e atualizei os códigos do primeiro post. Assim que eu tiver tempo eu faço o teste na máquina real e dou o feedback aqui.

Linha 10 a linha 12 tem um erro.
Se verdadeiro o bash vai criar uma pasta chamada “$TMP_DOWNLOADS” e eu nem sei se pode criar pasta com esse nome no File System.
Quando você uso a aspas simples o bash entende que é literal e então ele não expande a variável e mais eu nem sei o que o bash vai fazer com esse comando “mkdir” entre aspas duplas.

Código problemático:

if [ ! -d "$TMP_DOWNLOADS" ] ; then
    su "$SUDO_USER" -c "mkdir '$TMP_DOWNLOADS'"
fi

Código correto:

if [ ! -d "${TMP_DOWNLOADS}" ]
then
    su "${SUDO_USER}" -c mkdir "${TMP_DOWNLOADS}" || exit 1
fi

O conteudo das suas variáveis VGA_CHIP é muito ruim que tal usar:

VGA_CHIP="amd_intel_Ubuntu_18"		#placas de video AMD/Intel Ubuntu 18.04 ou 18.10
VGA_CHIP="amd_intel_Ubuntu_20"		#placas de video AMD/Intel Ubuntu 20

OU

VGA_CHIP="amd_intel_18"		#placas de video AMD/Intel Ubuntu 18.04 ou 18.10
VGA_CHIP="amd_intel_20"   	#placas de video AMD/Intel Ubuntu 20

linha 256 a 258 já que vc já habilito o -e porque não usar ele?
echo -e "OK\n\033[01;32m==================\033[0m\n"
Mesmo resultado menos numero de linha.

Linha 457 vai atualizar somente programas, mude para atualizar o sistema operacional.
apt update && apt dist-upgrade -y
Ou
apt update && apt full-upgrade -y
Antigamente usava o dist-upgrade mas os meninos de hoje estão usando o full mas fazem a mesma coisa.

Isso não parece funcionar em todas as versões do su – não importa o que venha depois, há um erro de mkdir: falta operando (testando no Mint 20.1)

Eu fiz um teste do meu script, coloquei na área de trabalho e executei ele com sudo. Para mim funcionou.
Se eu executar sem aspas assim:
su "$SUDO_USER" -c "mkdir $TMP_DOWNLOADS"
ele dá erro pois não entende que essa string deveria ser tudo junto: ‘área de trabalho’, ele entende que ‘/home/usuário/área’ não existe

Agora não tenho acesso ao linux, assim que estiver em casa vou testar suas dicas.
Obrigado

Se a sua versão do Bash for relativamente atualizada, é possível escrever o código como:

su "$SUDO_USER" -c "mkdir ${[email protected]}"

O bash vai automaticamente adicionar aspas, e processar apropriadamente aspas embutidas nas string (se houver):

$ A="Print's"
$ echo "${[email protected]}"
'Print'\''s'

(isso só funciona no Bash, no entanto)

Você tem razão o parâmetro para o “su” esta correto como vc diz.
O comando do @Capezotte também funciona, e é mais fácil de interpretar o seu causa um engano.

@aguamole @Capezotte

Seguindo a dica desse site:

$’…’ Protege uma string completamente, mas interpreta \n, \t, \a, etc $‘abc\n’

tem essa opção $’…’

Seria correto usar isso no meu caso, ou existe alguma inconsistência?
Testei o script abaixo na “Área de Trabalho” como sudo e funcionou pra mim. Isso é universal ou apenas para o bash, como no caso que o Capezotte citou acima?

Executado como sudo:

#!/usr/bin/env bash
PATH_BACKUP=${PWD}
TMP_DOWNLOADS=$PATH_BACKUP"/tmp-Backup-programas"

if [ ! -d "$TMP_DOWNLOADS" ] ; then
    su "$SUDO_USER" -c "mkdir $'TMP_DOWNLOADS'"
fi

e as Chaves deve sempre usar nas variáveis, ou quando é obrigatório e quando não é?

Tem que ler a documentação dos outros interpretadores para saber.
Mas o seu script esta sendo escrito para Bash.

Antes de tudo, $'' também não é universal, mas diferente do @Q não é exclusivo do Bash (não é como compatibilidade com outros shells seja algo para se preocupar aqui, 90% das distros têm o bash e 100% dos Linux Mint têm o mesmo).

Porém, ele não é a resposta aqui, e tem um problema parecido com o do '$TMP_DOWNLOADS'. O que ele quis dizer com “protege uma string” é que os espaços são interpretados como espaços em vez de separadores de argumentos. Subseguindo…

Há inconsistências. Você com certeza criou uma pasta chamada literalmente TMP_DOWNLOADS na pasta onde o script está localizado.

O principal problema é que o su -c pede um comando em shell, o qual vai ser interpretado de novo. É o motivo pelo qual você precisa de truques como "mkdir '$VARIAVEL'" ou, como eu sugeri, mkdir ${[email protected]}. Há dois “passes” de expansão:

  • Bash do script original, rodando como sudo: su -c "mkdir '$TMP_DOWNLOADS'"
  • Substituem-se as variáveis: su -c "mkdir '/onde/fica/tmp-Backup-programas'"
  • su inicia um novo shell como o usuário normal, que vai executar: mkdir '/onde/fica/tmp-Backup-programas'. Até aí tudo bem. Recomendo ${[email protected]} em vez de '$VARIAVEL' porque o primeiro cuida adequadamente de aspas dentro de aspas que possam aparecer.

Na versão seguinte:

  • Bash do script original, rodando como sudo: su -c "mkdir $'TMP_DOWNLOADS'"
  • Substituem-se as variáveis: su -c "mkdir $'TMP_DOWNLOADS'"
  • su inicia um novo shell como o usuário normal, que vai executar: mkdir $'TMP_DOWNLOADS'. Se você brincar no seu terminal aí, vai ver que ele cria literalmente uma pasta chamada TMP_DOWNLOADS

A intenção do $'' é facilitar o uso de caracteres como tabs e novalinhas dentro de scripts, por exemplo:

echo $'Olá mundo\nBem vindo'
# em vez de
echo 'Olá mundo
Bem vindo'

O ${[email protected]} é feito para cenários como esse, em que o shell tem que gerar texto a ser interpretado por outro shell. Tentar proteger o texto no argumento do su -c usando aspas normais ("", '' e $'') vai só introduzir riscos de bugs ao script.

É questão de estilo e completamente opcional, servindo mais para facilitar a visualização.

A única exceção é caso você vá incluir a variável em um texto e logo depois virão letras e números, aí as chaves servem para o shell não achar que o texto que vem depois é nome da variável.

# _ pode aparecer no nome de variáveis, chaves são necessárias
INICIAIS=mrk
INICIAIS_alvin=errado
NOME="${INICIAIS}_alvin" # certo, vai dar "mrk_alvin"
NOME="$INICIAIS_alvin" # errado, vai dar "errado"

# tanto faz, - não pode aparecer em variáveis e não há confusão
PASTA="$INICIAIS-downloads"
PASTA="${INICIAIS}-downloads"
2 curtidas

@aguamole @Capezotte @Natanael.755

Quero instalar dois pacotes no mesmo comando algo assim:
sudo apt install -y libreoffice-script-provider-python libreoffice-style-*

Estou fazendo uns testes na máquina real do script corrigido seguindo as orientações que vcs passaram. Mas esse comando não funciona se eu deixar a variável entre aspas.
vejam o exemplo:

Na linha 30

apt install -y “${package}”

se eu deixar assim, dá erro:

#!/usr/bin/env bash
set -e

declare -A pacotes_apt=(
    ["libreoffice-script-provider-python"]="libreoffice-script-provider-python libreoffice-style-*"
)


if [ ${#pacotes_apt[@]} -gt 0 ]; then
    echo ""
    echo -e "\e[01;44m \033[01;37m ╔════════════════════════════════╗   \033[0m"
    echo -e "\e[01;44m \033[01;37m ║ Instalando aplicativos via APT ║   \033[0m"
    echo -e "\e[01;44m \033[01;37m ╚════════════════════════════════╝█  \033[0m"
    echo -e "\e[01;44m \033[01;37m  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀  \033[0m"
    echo ""

    for i in "${!pacotes_apt[@]}"; do
        nome="$i"
        package="${pacotes_apt[$i]}"

        echo -e "\033[01;33m**** Instalando Aplicativo \033[01;37m${nome^^} \033[01;33mpelo comando: \033[01;32m$package\033[0m"
        #if ! dpkg -s "$nome" >/dev/null 2>&1 ; then # Só instala se já não estiver instalado

            #Skip EULA - ttf-mscorefonts-installer
            if [ "$package" == "ttf-mscorefonts-installer" ]; then
                echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections
            fi
            #####

            apt install -y "${package}"

        # else
        #     echo -e "\e[01;41m \033[01;37m[JÁ INSTALADO] - $package \033[0m \e[0m"
        # fi

        echo -e "OK\n\033[01;32m==================\033[0m\n"
    done
fi

Mensagem de erro

E: Impossível encontrar o pacote libreoffice-script-provider-python libreoffice-style-*


Se eu deixar assim sem aspas ele funciona, mas no shellcheck ele orienta deixar com aspas duplas
SC2086 · koalaman/shellcheck Wiki · GitHub :

#!/usr/bin/env bash
set -e

declare -A pacotes_apt=(
    ["libreoffice-script-provider-python"]="libreoffice-script-provider-python libreoffice-style-*"
)


if [ ${#pacotes_apt[@]} -gt 0 ]; then
    echo ""
    echo -e "\e[01;44m \033[01;37m ╔════════════════════════════════╗   \033[0m"
    echo -e "\e[01;44m \033[01;37m ║ Instalando aplicativos via APT ║   \033[0m"
    echo -e "\e[01;44m \033[01;37m ╚════════════════════════════════╝█  \033[0m"
    echo -e "\e[01;44m \033[01;37m  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀  \033[0m"
    echo ""

    for i in "${!pacotes_apt[@]}"; do
        nome="$i"
        package="${pacotes_apt[$i]}"

        echo -e "\033[01;33m**** Instalando Aplicativo \033[01;37m${nome^^} \033[01;33mpelo comando: \033[01;32m$package\033[0m"
        #if ! dpkg -s "$nome" >/dev/null 2>&1 ; then # Só instala se já não estiver instalado

            #Skip EULA - ttf-mscorefonts-installer
            if [ "$package" == "ttf-mscorefonts-installer" ]; then
                echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections
            fi
            #####

            apt install -y ${package}

        # else
        #     echo -e "\e[01;41m \033[01;37m[JÁ INSTALADO] - $package \033[0m \e[0m"
        # fi

        echo -e "OK\n\033[01;32m==================\033[0m\n"
    done
fi

Onde está o problema?

É o seguinte, com o asterisco caso exista algum arquivo no diretório com esse nome, ele será passado como parâmetro ao invés do nome do pacote, por isso o shellcheck orienta usar aspa, porém ao fazer isso o APT trata como nome do pacote e então você você tem esse erro:

Nesse caso o que você precisa fazer é transformar em uma expressão de busca:

"^libreoffice-style-.*"

Isso vai dizer pro APT:

Pesquise por todos os pacotes que comecem (^) com libreoffice-style- independente de como termine (.* no final, sempre que quiser usar o * coloque um . antes)

Só mais uma coisa, essa declaração tem um problema estrutural:

Você está usando arrays associativos procure usar arrays indexados, pro seu uso de casos é bem mais tranquilo:

declare -a pacotes_apt=("pacote1" "pacote2" "pacote3")
2 curtidas

Para salvar as configurações do GSettings usei o dconf com esse comando:
dconf dump / > MEU_HD_BACKUP/Pos-Install/Sistema/mint_config.dconf

Fiz a correção seguindo as orientações e testei e funcionou na maquina real:
disposição dos arquivos que devem ser salvos para backup, onde ‘[d]’ significa que um diretório.:

[d]home
    [d]Applications
        [d]ksnip
            [d].config
                [d]ksnip
                    ksnip.conf

    [d]Modelos
        {***tudo dessa pasta}

    [d].android
        adbkey
        adbkey.pub

    [d].config
        [d]autostart
            Mutar Audio (.desktop que aponta para um script personalizado)

        [d]Code
            {***tudo dessa pasta}

        [d]gtk-3.0
            bookmarks

        [d]libreoffice
            {***tudo dessa pasta}

        [d]lutris
            system.yml

        [d]meus_scripts
            {***tudo dessa pasta personalizada}

        [d]nemo
            bookmark-metadata
            desktop-metadata

        [d]smplayer
            {***tudo dessa pasta}

        [d]streamlink
            [d]plugins
                {***tudo dessa pasta}

        [d]VirtualBox
            VirtualBox.xml

        mimeapps.list

    [d].kodi
        {***tudo dessa pasta}

    [d].local
        [d]applications
            Spotify Web

        [d]ice
            [d]firefox
                {***todas as pastas de webapps}

        [d]icons
            [d]hicolor
                [d]512x512
                    [d]apps
                        {***tudo dessa pasta}

        [d]keyrings
            login.keyring
            user.keystore

    [d].mozilla
        {***tudo dessa pasta}

    [d].snes9x
        snes9x.xml

    [d].steam
        [d]debian-installation
            [d]appcache
                appinfo.vdf
                localization.vdf
                packageinfo.vdf

            [d]config
                config.vdf
                DialogConfig.vdf
                libraryfolders.vdf
                loginusers.vdf

            [d]steamapps
                libraryfolders.vdf

            [d]userdata
                {***tudo dessa pasta}

            update_hosts_cached.vdf

        registry.vdf
        steam.pid
        steam.token

    captura_stream.py

[d]Sistema
    [d]icons
        Mint-Y-Dark-Yellow-Rainbow.tar.gz

    [d]scripts
        [d]profile.d
           {***tudo dessa pasta}

    [d]themes
        themes-Royal.tar.gz

    mint_config.dconf
    official-package-repositories.list

script corrigido (arquivo único - instala programas e configura ambiente e programas no Mint Cinnamon):