Script para Criação de Pendrive bootavel do Windows


  JG-Tux

Eu sei que existem diversas ferramentas, como Ventoy, WoeUSB, Unetbootin, GParted e outras, que facilitam a criação de um pendrive inicializável de forma eficiente. No entanto, estou aprendendo Bash e decidi criar meu próprio script com essa finalidade.

Antes do lançamento do Windows 11, eu costumava usar a biblioteca wimlib para comprimir ao máximo o arquivo install.wim, garantindo que ele tivesse menos de 4 GB. Isso permitia que ele fosse armazenado em um pendrive formatado em FAT32. No entanto, com o Windows 11, o tamanho do arquivo install.wim aumentou consideravelmente, e mesmo após a compressão, ele pode ultrapassar os 4 GB. Isso inviabiliza a utilização de sistemas de arquivos FAT32.

Recentemente, encontrei uma solução utilizando o ntfs-3g para formatar o pendrive como NTFS. Essa abordagem me permite simplesmente extrair a ISO do Windows para o pendrive, tornando todo o processo mais rápido e eficiente. No entanto, vale ressaltar que, se o script for interrompido durante a instalação, será necessário reiniciar a máquina para que o sistema reconheça o pendrive novamente.

Este script suporta distros derivadas do Debian, Arch Linux e Fedora. No entanto, o último teste foi realizado somente no Arch Linux. Aceito sugestões/pr de como melhorar o script.

Como Usar

Siga estas etapas:

  1. Baixe a ISO do Windows diretamente do site oficial da Microsoft.

  2. Abra o terminal e navegue até o diretório onde você baixou a ISO.

  3. Execute o seguinte comando no terminal:

    curl -o windusb.sh https://raw.githubusercontent.com/Broly1/Windusb/master/windusb.sh && chmod +x windusb.sh && ./windusb.sh
    

Isso baixará automaticamente o script Windusb, tornará o script executável e o executará. O script guiará você pelo processo de criação do pendrive inicializável.

GitHub

11 curtidas

Bacana! Scripts são bem úteis embora seja uma linguagem bem difícil por ter vários jeitos de fazer as mesmas coisas, não ter tipos fortes, e também regras estranhas de conversão de tipos.

A parte mais difícil da programação na maioria das vezes nem é fazer o que precisa ser feito, mas sim verificar que você tem todos os ingredientes antes de começar. Um script pra fritar um ovo seria bastante simples se for “Quebre o ovo na frigideira com um pouco de óleo e fogo baixo, aguarde 2 minutos, desligue o fogo, coma o ovo”. Nesse ponto o script funciona perfeitamente para você pois vc já conhece o seu fogão, sua geladeira e sua despensa. Porém o script para fritar um ovo em qualquer lugar não pode ser assim, pois alguém na Finlândia que pega a frigideira, coloca óleo, começa a esquentar, pega o ovo, IHHH não tem ovo, terminou o script mas a panela ficou no fogo ligado! A receita para fritar um ovo pode virar uma receita para estragar uma panela…

Pessoalmente eu uso bastante scripts feitos por mim, e quando procuro ou vejo o script de alguém, pego as partes interessantes para fazer meu próprio. Scripts para divulgação geral são inseguros para um usuário comum (não programador) executar, especialmente quando precisa ser executado em modo de administrador. Uma vez que seja dada a senha, pode acontecer qualquer coisa, inclusive o que a pessoa espera que aconteça! Eu jamais recomendo que pessoas saiam executando código de terceiros (que não são de programas oficiais da distribuição).

Isso posto, e imaginando que esse script seria incluído em um programa oficial nas distribuições, algumas considerações minhas seriam:

Verificar todas as dependências antes de iniciar o programa.

Severidade alta. Pensei em um array de comandos usados e comandos de verificação. Incluiria todos eles para verificação em loop. Ao não achar um programa (ou melhor ainda se uma versão antiga incompatível for encontrada), o script se encerra com uma mensagem. No caso de você querer adicionar suporte a várias distribuições, daí sim usar o comando para instalar o pacote que provê o referido programa, e reinicia a verificação. Você pensou nisso e verificou o ntfs-3g e p7zip, mas o script também usa sudo, sgdisk, wipefs. Isso evita do seu programa acabar no meio com “XXXX not found”.

Comentários são legais, mas não abuse

Severidade baixa. A princípio o nome das funções e variáveis devem ser auto explicativos, de modo que os comentários devem conter informações adicionais relevantes, mas evitar a explicação do código em si, que deve ser legível. Evite especialmente comentar linha a linha, a menos que seja um exercício de aprendizado. Comentar cada linha também é comportamento padrão dos geradores automáticos de código por inteligência artificial, então dá um jeitão de código pré-fabricado ao seu programa.

Seleção da iso

Severidade: baixa. O programa está bem legal nas seleções, mas pegar simplesmente a primeira iso não ficou bom. O ideal seria uma nova seleção com todos os arquivos iso que foram achados no diretório para o usuário escolher qual será escrita.

Funções são específicas

Severidade alta. Uma das piores práticas (e das mais fáceis de fazer) é começar a inchar funções simples com outras tarefas. Veja que a função format_drive está também selecionando a ISO e verificando dependências. Não faz sentido estar ali, mesmo que comentado. Crie funções específicas na parte principal do script. Eu acho que nem precisaria essa função, uma vez a função partformat faz essas tarefas mas com outro nome.

Nomes de variáveis e funções

Severidade: terrível (isso pode acabar com um projeto). Geralmente um programa segue regras sobre os nomes, as duas principais são a capitalização ou o símbolo sublinhado. Se o programa é seu, vc que escolhe, mas mantenha a coerência. Veja que a função format_drive está com sublinhado, mas partformat está da pior forma possível: abreviada e sem diferenciação. Esse é o verdadeiro terror até para você mesmo no futuro. Em um outro programa sem coerência isso poderia ser abreviação de ‘packed real-time formatter’.

Parâmetros

Severidade média. Embora o seu script não necessite nenhum parâmetro para funcionamento, a função principal está usando, e passando isso para as sub funções que também não necessitam. Embora deixar não cause problema no script, ele causa confusão para quem tenta entendê-lo pois imagina que será usado em algum momento.

4 curtidas

Opa valeu pelas dicas, estou procurando uma forma melhor de checagem de software usando o package manager,
no caso do sgdisk ele já vem preinstalado nas distros que testei mas tb quero adicioná-lo a essa checagem,
E no caso de seleção da ISO vou criar uma função que se tiver somente uma ISO o script continua sem prompt se tiver duas ou mais ele coloca em um menu de escolha como a do pendrive, e também tem o problema de arquivos com nomes parecidos e auto complete, outra maneira q pensei foi fazer o drop da ISO no terminal para pegar o Path, porém pelo que pesquisei os terminais funcionam diferente em desktops diferentes e isso pode não funcionar em algumas distros então abandonei essa ideia.
No caso dos nomes de variáveis esse é o mais fácil de resolver assim como os comentários :grinning:.
já no caso do parâmetro não entendi bem o q quiz dizer, paço augumas funções pelo loop para mostrar o prompt para o usuário escolher o pendrive e se aceita continuar o script e tal, se quiser elaborar um pouco mais manda bala.

2 curtidas

Fixed! :+1:

1 curtida

Mané usar WoeUSB. Parabéns pelo projeto, fera

4 curtidas

Na linha 129 troque “$iso_file” por “${iso_file[@]}”

1 curtida

Pronto resolvido esse bo

get_the_iso() {
	iso_files=(Win*.iso)

	if [ ${#iso_files[@]} -eq 0 ]; then
		clear
		printf "No Windows ISO files found in the current directory.\n"
		exit 1
	fi

	if [ ${#iso_files[@]} -eq 1 ]; then
		iso_path="${iso_files[0]}"
		printf "Windows ISO found: %s\n" "$iso_path"
	else
		clear
		printf "Multiple Windows ISO files found:\n"

		select iso_path in "${iso_files[@]}"; do
			if [ -n "$iso_path" ]; then
				printf "Selected Windows ISO: %s\n" "$iso_path"
				break
			else
				printf "Invalid selection. Please choose a valid option.\n"
			fi
		done
	fi
}

Virou um espaguete mas tb resolveu.

# Search the system  if the packages we need is already installed
install_apt_package() {
    local package_name="$1"
    if ! dpkg -l "$package_name" > /dev/null 2>&1; then
        apt update
        apt install -y "$package_name"
    else
        printf "Package %s '$package_name' is already installed (APT).\n"
    fi
}

install_dnf_package() {
    local package_name="$1"
    if ! rpm -q "$package_name" > /dev/null 2>&1; then
        dnf install -y "$package_name"
    else
        printf "Package %s '$package_name' is already installed (DNF).\n"
    fi
}

install_pacman_package() {
    local package_name="$1"
    if ! pacman -Q "$package_name" > /dev/null 2>&1; then
        pacman -Sy --noconfirm --needed "$package_name"
    else
        printf "Package %s '$package_name' is already installed (Pacman).\n"
    fi
}

# Install the missing packages if we dont have them
install_missing_packages() {
	clear
	cat <<"EOF"
#############################
#  Installing Dependencies  #
#############################
EOF
debian_packages=("ntfs-3g" "p7zip-full" "gdisk")
fedora_packages=("ntfs-3g" "p7zip-plugins" "gdisk")
arch_packages=("ntfs-3g" "p7zip" "gptfdisk")

# Check for the distribution type and call the appropriate function
if [[ -f /etc/debian_version ]]; then
    for package in "${debian_packages[@]}"; do
        install_apt_package "$package"
    done
elif [[ -f /etc/fedora-release ]]; then
    for package in "${fedora_packages[@]}"; do
        install_dnf_package "$package"
    done
elif [[ -f /etc/arch-release ]]; then
    for package in "${arch_packages[@]}"; do
        install_pacman_package "$package"
    done
else
    printf "Your distro is not supported!\n"
    exit 1
fi
}

GitHub

2 curtidas

Ficarei muito suspeito se o Balena etcher começar a dar suporte para o Windows agora
Estão visitando meu script no github tem q dar pelo menos os creditos. :rofl:

2 curtidas

Eu tenho um script simples que cria pendrives bootáveis para instalação de Linux, utilizando o comando ‘dd’. Funciona muito bem e não preciso depender desses softwares de terceiros, que vira e mexe dão pau. Além de ser compatível com qualquer distro, eu creio. :grin:

1 curtida

Ficou muito legal o seu script. Parabéns!

2 curtidas

Uma coisa que até hoje não descobri é por que, quando, por exemplo, eu extraio a ISO do Windows com o 7z ou monto e copio manualmente, essa cópia ou extração parece concluída, mas não está. Pelo que li em muitos fóruns, o Linux sobe tudo para a memória RAM, mostra como concluído e depois exporta para o pendrive. Isso é um problema, especialmente com aqueles pendrives mais baratos, que demoram até 30 minutos para transferir os dados sem mostrar absolutamente nada na tela. A maioria das pessoas acha que já terminou ou que travou, então acaba removendo o pendrive antes da hora. Eu queria muito uma solução para isso. Talvez tenha sido isso que aconteceu comigo quando usei o Ventoy e deu problema com o Windows. Se houvesse um jeito de usar o dd para copiar para uma partição NTFS, isso resolveria o meu problema.

3 curtidas

Criar pendrive de Windows no Linux é sempre um problema. :rage:

O comando dd do Linux é realmente espetacular, muito poderoso. :star_struck:

2 curtidas

Essas dicas são de como desenvolver um programa e não um script.
Script são comandos alinhados um após o outro, um programa tem codigo estruturado, tratamento de erro, regras de variaveis, boas praticas de programação e mais uma porrada de orientações a serem seguidas, para aprender a como criar programas profissionais de shell, leia o livro

Shell Script Profissional
Livro por Aurelio Marinho Jargas

Ele da uma serie de orientações de como desenvolver um programa profissional em Shell, com estas orientações vc será um programador decente e não um scripteiro.

Isso não faz sentido, primeiro que vc pode forçar o script a abrir apenas em um shell especifico, e segundo que se vc não colocar a shebang o código vai ser aberto em qualquer shell que o usuário definir, isso significa que vc pode colocar um if ou um case para que o código detecte automaticamente qual shell ele está sendo executado e bifurca a execução automaticamente para o trecho especifico do código compatível com o shell que esta executando o código.

Isso que ele sugeriu é otimização de código na verdade, e não um fix, só para acrescentar mesmo.

Vc coloco no final \n era melhor usar echo para ficar visualmente mais simples de entender.

O nome disso é cache de disco, é um espaço reservado na memória RAM que serve para otimizar o desempenho de gravação e leitura em dispositivo de armazenamento.
Acredito que de para desabilitar, mas nunca pesquisei.

Aqui: c - Disabling disk cache in linux - Stack Overflow
O usuário nio diz que para desativar a cache de disco no dispositivo desejado é o comando “hdparm” com o parâmetro -W(maiúsculo) e na frente coloca quanto de cache desejada, no caso 0(zero), lendo o manual do hdparm no parâmetro -W diz:

-W Obter/define o recurso de cache de gravação da unidade IDE/SATA.

Então segundo o manual do hdparm é isso mesmo.
Lembre de colocar um if “command -v hdparm” para checar se o hdparm esta disponível no sistema, e se não estiver, notifique o usuário que pode ser que o script não funcione corretamente.

Tem como usar o sync mas dai não melhora o desenpenho somente copia em tempo real sem cache mesmo outro dia tava testando maneiras diferentes de montagem para ver se ficava mais rapido o umount, não vi diferença nenhuma, ainda estou pesquisando parametos do mount umount tipo.


mount -o rw,noatime,flush,big_writes,uid=1000,gid=1000,umask=022 "${drive}1" "${usb_mount_point}"
1 curtida

Desabilita a cache de disco usando o hdparm.
A ta, vc quer uma forma de gravar mais rápido desabilitando a cache, bom, não é possível fazer isso, porque é uma limitação de hardware, limitações de hardware não da para ser modificado via software, só o que da é para mitigar e é isso que faz a cache de disco.

Vou testar aqui.

1 curtida