One place for hosting & domains

      Cómo usar Rsync para sincronizar directorios locales y remotos


      Introducción

      Rsync, que significa “sincronización remota”, es una herramienta de sincronización de archivos remotos y locales. Utiliza un algoritmo que minimiza la cantidad de datos copiados, moviendo solo las partes de los archivos que cambiaron.

      En esta guía, explicaremos el manejo básico de esta potente utilidad.

      ¿Qué es Rsync?

      Rsync es una herramienta de sincronización muy flexible y habilitada para la red. Debido a su presencia universal en sistemas Linux y sistemas similares a Unix, y su popularidad como herramienta para las secuencias de comandos del sistema, se incluye en la mayoría de las distribuciones de Linux de manera predeterminada.

      Sintaxis básica

      La sintaxis básica de rsync es muy sencilla, y opera de forma similar a ssh, scp y cp.

      Crearemos dos directorios de prueba y algunos archivos de prueba con los siguientes comandos:

      • cd ~
      • mkdir dir1
      • mkdir dir2
      • touch dir1/file{1..100}

      Ahora, tenemos un directorio llamado dir1 con 100 archivos vacíos.

      Output

      file1 file18 file27 file36 file45 file54 file63 file72 file81 file90 file10 file19 file28 file37 file46 file55 file64 file73 file82 file91 file100 file2 file29 file38 file47 file56 file65 file74 file83 file92 file11 file20 file3 file39 file48 file57 file66 file75 file84 file93 file12 file21 file30 file4 file49 file58 file67 file76 file85 file94 file13 file22 file31 file40 file5 file59 file68 file77 file86 file95 file14 file23 file32 file41 file50 file6 file69 file78 file87 file96 file15 file24 file33 file42 file51 file60 file7 file79 file88 file97 file16 file25 file34 file43 file52 file61 file70 file8 file89 file98 file17 file26 file35 file44 file53 file62 file71 file80 file9 file99

      También tenemos un directorio vacío llamado dir2.

      Para sincronizar el contenido de dir1 a dir2 en el mismo sistema, escriba lo siguiente:

      La opción -r significa recursiva, que es necesaria para la sincronización de directorios.

      También podríamos utilizar el indicador -a en su lugar:

      La opción -a es un indicador combinado. Significa “archivo” y sincroniza de manera recursiva, además conserva los enlaces simbólicos, los archivos especiales y de dispositivo, fechas de modificación, grupo, propietario y permisos. Se utiliza más con más frecuencia que -r y, generalmente, es lo que querrá utilizar.

      Nota importante

      Es posible que haya notado que hay una barra diagonal (/) al final del primer argumento en los comandos anteriores:

      Eso es necesario para referirse a “el contenido de dir1”. La alternativa, sin la barra diagonal, colocaría dir1, incluyendo el directorio, dentro de dir2. Eso crearía una jerarquía similar a esta:

      Siempre compruebe los argumentos antes de ejecutar un comando rsync. Rsync ofrece un método para hacer esto pasando las opciones -n o --dry-run. El indicador -v (para modo detallado) también es necesario para obtener el resultado adecuado:

      Output

      sending incremental file list ./ file1 file10 file100 file11 file12 file13 file14 file15 file16 file17 file18 . . .

      Compare este resultado con el resultado que obtenemos cuando eliminamos la barra diagonal:

      Output

      sending incremental file list dir1/ dir1/file1 dir1/file10 dir1/file100 dir1/file11 dir1/file12 dir1/file13 dir1/file14 dir1/file15 dir1/file16 dir1/file17 dir1/file18 . . .

      Puede ver que el directorio en sí se transfiere.

      Cómo usar Rsync para sincronizar con un sistema remoto

      La sincronización con un sistema remoto es trivial si tiene acceso SSH al equipo remoto y rsync instalado en ambos sitios. Una vez que tenga el acceso SSH verificado entre los dos equipos, puede sincronizar la carpeta dir1 anterior con una computadora remota utilizando esta sintaxis (tenga en cuenta que, en este caso, queremos transferir el propio directorio, por lo que omitimos la barra diagonal):

      • rsync -a ~/dir1 username@remote_host:destination_directory

      Eso se conoce como una operación “push” porque empuja un directorio del sistema local a un sistema remoto. La operación opuesta se conoce como “pull”. Se utiliza para sincronizar un directorio remoto con el sistema local. Si el dir1 estuviera en el sistema remoto, y no en nuestro sistema local, la sintaxis sería la siguiente:

      • rsync -a username@remote_host:/home/username/dir1 place_to_sync_on_local_machine

      Al igual que el cp y otras herramientas similares, la fuente siempre es el primer argumento, y el destino siempre es el segundo.

      Opciones útiles para Rsync

      Rsync proporciona muchas opciones para alterar el comportamiento predeterminado de la utilidad. Ya hablamos de algunos de los indicadores más importantes.

      Si está transfiriendo archivos que aún no se comprimieron, como los archivos de texto, puede reducir la transferencia de la red comprimiendo con la opción -z:

      • rsync -az source destination

      El indicador -P es muy útil. Combina los indicadores --progress y --partial. El primero de ellos le proporciona una barra de progreso para las transferencias, y el segundo le permite reanudar las transferencias interrumpidas:

      • rsync -azP source destination

      Output

      sending incremental file list ./ file1 0 100% 0.00kB/s 0:00:00 (xfer#1, to-check=99/101) file10 0 100% 0.00kB/s 0:00:00 (xfer#2, to-check=98/101) file100 0 100% 0.00kB/s 0:00:00 (xfer#3, to-check=97/101) file11 0 100% 0.00kB/s 0:00:00 (xfer#4, to-check=96/101) . . .

      Si volvemos a ejecutar el comando, obtendremos un resultado más corto porque no se produjeron cambios. Eso ilustra la capacidad de rsync de utilizar las fechas de modificación para determinar si se realizaron cambios.

      • rsync -azP source destination

      Output

      sending incremental file list sent 818 bytes received 12 bytes 1660.00 bytes/sec total size is 0 speedup is 0.00

      Podemos actualizar la fecha de modificación en algunos de los archivos y ver que rsync vuelve a copiar de manera inteligente solo los archivos modificados:

      • touch dir1/file{1..10}
      • rsync -azP source destination

      Output

      sending incremental file list file1 0 100% 0.00kB/s 0:00:00 (xfer#1, to-check=99/101) file10 0 100% 0.00kB/s 0:00:00 (xfer#2, to-check=98/101) file2 0 100% 0.00kB/s 0:00:00 (xfer#3, to-check=87/101) file3 0 100% 0.00kB/s 0:00:00 (xfer#4, to-check=76/101) . . .

      Para mantener dos directorios realmente sincronizados, es necesario eliminar los archivos del directorio destino si se eliminan de la fuente. De forma predeterminada, rsync no elimina nada del directorio de destino.

      Podemos cambiar este comportamiento con la opción --delete. Antes de utilizar esta opción, utilice la opción --dry-run y realice pruebas para evitar la pérdida de datos:

      • rsync -a --delete source destination

      Si desea excluir ciertos archivos o directorios ubicados en un directorio que está sincronizando, puede hacerlo especificándolos en una lista separada por comas, siguiendo la opción --exclude=:

      • rsync -a --exclude=pattern_to_exclude source destination

      Si especificamos un patrón para excluir, podemos anular esa exclusión para archivos que coincidan con un patrón diferente utilizando la opción --include=.

      • rsync -a --exclude=pattern_to_exclude --include=pattern_to_include source destination

      Por último, la opción --backup de rsync se puede utilizar para almacenar copias de seguridad de archivos importantes. Se utiliza en conjunto con la opción --backup-dir, que especifica el directorio en donde las copias de seguridad de los archivos se deben almacenar.

      • rsync -a --delete --backup --backup-dir=/path/to/backups /path/to/source destination

      Conclusión

      Rsync puede simplificar la transferencia de archivos a través de conexiones de red y robustecer la sincronización de directorios locales. La flexibilidad de rsync lo convierte en una buena opción para muchas operaciones con diferentes niveles de archivo.

      Dominar rsync le permite diseñar operaciones de respaldo complejas y obtener un control detallado sobre qué se transfiere y cómo.



      Source link

      Como converter tipos de dados em Python 3


      Introdução

      Na linguagem Python, os tipos de dados são usados para classificar um tipo específico de dados, determinando os valores que você pode atribuir ao tipo e as operações que você pode realizar nele. Ao programar, há momentos em que será necessário converter valores entre os no tipos, no intuito de manipular tais valores de maneira diferente. Por exemplo, talvez seja necessário concatenar valores numéricos com strings, ou representar casas decimais em números que foram inicializados como valores de número inteiro.

      Este tutorial irá ensinar a converter tipos de dados, incluindo números, strings, tuplas e listas, bem como fornecer exemplos para ajudar você a familiarizar-se com diferentes casos de uso.

      Convertendo os tipos de número

      Em Python, existem dois tipos de dados numéricos: inteiros e números de ponto flutuante (float). Às vezes, ao trabalhar no código de outra pessoa, será necessário converter um inteiro para um float ou vice-versa. Em outros casos, você pode estar usando um inteiro quando o que realmente precisa é de um float. O Python possui métodos integrados para permitir a conversão de inteiros em floats e floats em inteiros.

      Convertendo os números inteiros em floats

      O método float() do Python irá converter inteiros em floats. Para usar essa função, adicione um inteiro dentro dos parênteses:

      float(57)
      

      Neste caso, 57 será convertido em 57.0.

      Também é possível usar essa técnica com uma variável. Vamos declarar f como igual a 57, e então imprimir o novo float:

      f = 57
      print(float(f))
      

      Output

      57.0

      Usando a função float(), podemos converter inteiros em floats.

      Convertendo floats em inteiros

      O Python também possui uma função integrada para converter floats em inteiros: int().

      A função int() funciona de maneira semelhante à função float(): é possível adicionar um número de ponto flutuante dentro dos parênteses para convertê-lo em um inteiro:

      int(390.8)
      

      Neste caso, 390.8 será convertido em 390.

      Você também pode usar essa técnica com as variáveis. Vamos declarar b como igual a 125.0, e c como igual a 390.8, e então imprimir os novos floats:

      b = 125.0
      c = 390.8
      
      print(int(b))
      print(int(c))
      

      Output

      125 390

      Ao converter os floats em inteiros com a função int(), o Python corta a casa decimal e os números do float que restam são usados para criar um inteiro. Embora talvez você queira arredondar 390,8 para 391, o Python não fará isso através da função int().

      Números convertidos através de divisão

      Em Python 3, quocientes relevantes são convertidos de inteiros para floats ao fazer uma divisão, embora não sejam em Python 2. Ou seja, quando você dividir 5 por 2, em Python 3, você receberá um float como resposta (2.5):

      a = 5 / 2
      print(a)
      

      Output

      2.5

      Em Python 2, como você estava lidando com dois inteiros, você receberia um inteiro de volta como sua resposta: 5 / 2 = 2. Leia “Python 2 vs Python 3: considerações práticas“ para mais informações sobre as diferenças entre o Python 2 e Python 3.

      Uma string é uma sequência de um ou mais caracteres (letras, números ou símbolos). As strings são uma forma comum de dados em programas de computador. Muitas vezes, pode ser necessário converter strings em números e números em strings, especialmente quando estivermos incluindo dados gerados pelo usuário.

      Convertendo números em strings

      Podemos converter números em strings usando o método str(). Vamos passar um número ou uma variável dentro dos parênteses do método e então esse valor numérico será convertido em um valor de string.

      Primeiro, vamos ver como converter inteiros. Para converter o inteiro 12 em um valor de string, passe o número 12 para o método str():

      str(12)
      

      Ao executar str(12) no shell interativo do Python com o comando python em uma janela de terminal, você receberá o seguinte resultado:

      Output

      '12'

      As aspas ao redor do número 12 significam que o número já não é mais um inteiro, mas sim um valor de string.

      Com variáveis, podemos começar a ver como é prático converter inteiros em strings. Vamos supor que queiramos monitorar o progresso diário de um usuário na programação e estamos inserindo quantas linhas de código eles estão escrevendo por vez. Queremos mostrar esse feedback para o usuário. Para tanto, os valores de string e inteiro serão impressos ao mesmo tempo:

      user = "Sammy"
      lines = 50
      
      print("Congratulations, " + user + "! You just wrote " + lines + " lines of code.")
      

      Ao executar este código, iremos receber o seguinte erro:

      Output

      TypeError: Can't convert 'int' object to str implicitly

      Não é possível concatenar strings e inteiros em Python, de modo que teremos que converter a variável lines para se tornar um valor de string:

      user = "Sammy"
      lines = 50
      
      print("Congratulations, " + user + "! You just wrote " + str(lines) + " lines of code.")
      

      Agora, ao executar o código, iremos receber o resultado a seguir, parabenizando o usuário pelo progresso alcançado:

      Output

      Congratulations, Sammy! You just wrote 50 lines of code.

      Se quisermos converter um float em uma string, ao invés de um inteiro em uma string, seguimos os mesmos passos e formatos. Ao passar um float no método str(), um valor de string do float será retornado. Podemos usar o valor do float em si ou uma variável:

      print(str(421.034))
      
      f = 5524.53
      print(str(f))
      

      Output

      421.034 5524.53

      Vamos fazer um teste para garantir que tudo está correto, fazendo a concatenação com uma string:

      f = 5524.53
      print("Sammy has " + str(f) + " points.")
      

      Output

      Sammy has 5524.53 points.

      Agora, temos certeza de que o float foi convertido corretamente em uma string, pois a concatenação foi realizada sem nenhum erro.

      Convertendo strings em números

      As strings podem ser convertidas em números usando os métodos int() e float().

      Se sua string não tiver casas decimais, você provavelmente vai querer convertê-la em um número inteiro, usando o método int().

      Vamos usar o exemplo do usuário Sammy, monitorando as linhas de código escritas a cada dia. Pode ser que queiramos manipular esses valores com operações matemáticas, no intuito de dar um feedback mais interessante para o usuário. Porém, no momento, tais valores estão armazenados em strings:

      lines_yesterday = "50"
      lines_today = "108"
      
      lines_more = lines_today - lines_yesterday
      
      print(lines_more)
      

      Output

      TypeError: unsupported operand type(s) for -: 'str' and 'str'

      Como os dois valores numéricos foram armazenados em strings, um erro foi emitido. O operando - para a subtração não é um operando válido para dois valores de string.

      Modifique o código para incluir o método int() que converterá as strings em inteiros, permitindo, assim, fazer operações matemáticas com os valores que eram originalmente strings.

      lines_yesterday = "50"
      lines_today = "108"
      
      lines_more = int(lines_today) - int(lines_yesterday)
      
      print(lines_more)
      

      Output

      58

      A variável lines_more é automaticamente um inteiro, sendo igual ao valor numérico de 58 neste exemplo.

      Também é possível converter os números no exemplo acima em valores float usando o método float() no lugar do método int(). Em vez de receber o resultado de 58, iremos receber o resultado de 58.0, um float.

      O usuário Sammy está ganhando pontos em valores decimais.

      total_points = "5524.53"
      new_points = "45.30"
      
      new_total_points = total_points + new_points
      
      print(new_total_points)
      

      Output

      5524.5345.30

      Neste caso, usar o operando + com duas strings é uma operação válida, mas irá concatenar duas strings ao invés de fazer a adição de dois valores numéricos. Então, nosso resultado parece não convencional, pois apenas coloca os dois valores um ao lado do outro.

      Precisamos converter essas strings em floats antes de executar qualquer operação matemática com o método float():

      total_points = "5524.53"
      new_points = "45.30"
      
      new_total_points = float(total_points) + float(new_points)
      
      print(new_total_points)
      

      Output

      5569.83

      Agora que convertemos as duas strings em floats, recebemos o resultado esperado que adiciona 45.30 a 5524.53.

      Se tentarmos converter um valor de string com casas decimais em um inteiro, iremos receber um erro:

      f = "54.23"
      print(int(f))
      

      Output

      ValueError: invalid literal for int() with base 10: '54.23'

      Se passarmos um valor decimal em uma string para o método int(), iremos receber um erro, pois ele não será convertido em um inteiro.

      Converter strings em números nos permite modificar rapidamente o tipo de dados com o qual estamos trabalhando para que possamos realizar operações com valores numéricos que eram originalmente strings.

      Convertendo em tuplas e listas

      Os métodos list() e tuple() podem ser usados para converter os valores passados a eles nos tipos de dados lista e tupla respectivamente. Em Python:

      • uma lista é uma sequência ordenada mutável de elementos que fica contida dentro de colchetes [ ].
      • uma tupla é uma sequência ordenada imutável de elementos contida dentro de parênteses ( ).

      Convertendo em tuplas

      Vamos começar com a conversão de uma lista em uma tupla. Converter uma lista em uma tupla, que é um tipo de dados imutável, pode permitir uma otimização substancial aos programas que criamos. Quando usamos o método tuple(), ela irá retornar a versão em tupla do valor passado a ele.

      print(tuple(['pull request', 'open source', 'repository', 'branch']))
      

      Output

      ('pull request', 'open source', 'repository', 'branch')

      Vemos que uma tupla foi impressa no resultado, pois os itens estão agora contidos dentro de parênteses ao invés de colchetes.

      Vamos usar tuple() com uma variável que representa uma lista:

      sea_creatures = ['shark', 'cuttlefish', 'squid', 'mantis shrimp']
      print(tuple(sea_creatures))
      

      Output

      ('shark', 'cuttlefish', 'squid', 'mantis shrimp')

      Novamente, vemos que o valor de lista foi alterado para um valor de tupla, indicado pelos parênteses. Podemos converter qualquer tipo iterável em uma tupla, incluindo strings:

      print(tuple('Sammy'))
      

      Output

      ('S', 'a', 'm', 'm', 'y')

      Considerando que é possível iterar em strings, podemos convertê-las em tuplas com o método tuple(). Entretanto, com tipos de dados que não são iteráveis, como inteiros e floats, iremos receber um erro do tipo:

      print(tuple(5000))
      

      Output

      TypeError: 'int' object is not iterable

      Embora seja possível converter um inteiro em uma string, para então converter em uma tupla, como em tuple(str(5000)), é melhor escolher um código legível ao invés de conversões complicadas.

      Convertendo em listas

      Converter valores, especialmente tuplas, em listas, pode ser útil quando for necessário ter uma versão mutável desse valor.

      Vamos usar o método list() para converter a tupla a seguir em uma lista. Como a sintaxe para criar uma lista usa parênteses, certifique-se de incluir os parênteses do método list() e, neste caso, também o método print():

      print(list(('blue coral', 'staghorn coral', 'pillar coral')))
      

      Output

      ['blue coral', 'staghorn coral', 'pillar coral']

      Os colchetes indicam que uma lista foi retornada a partir do valor de tupla original passado ao método list().

      Para tornar o código mais legível, podemos remover um dos pares de parênteses usando uma variável:

      coral = ('blue coral', 'staghorn coral', 'pillar coral')
      list(coral)
      

      Caso imprimíssemos list(coral), iríamos receber o mesmo resultado que acima.

      Assim como as tuplas, as strings podem ser convertidas em listas:

      print(list('shark'))
      

      Output

      ['s', 'h', 'a', 'r', 'k']

      Aqui, a string 'shark' foi convertida em uma lista, fornecendo uma versão mutável do valor original.

      Conclusão

      Este tutorial de Python demonstrou como converter vários dos tipos de dados nativos importantes em outros tipos de dados, principalmente através de métodos integrados. Ser capaz de converter tipos de dados em Python fornece uma flexibilidade extra ao escrever seus programas.



      Source link

      Como ler e definir variáveis de ambiente e de shell no Linux


      Introdução

      Ao interagir com seu servidor através de uma sessão do shell, há muitas informações compiladas pelo seu shell para determinar o seu comportamento e acesso a recursos. Algumas dessas configurações estão contidas nas definições de configuração enquanto outras são determinadas pela entrada do usuário.

      Uma das maneiras pela qual o shell mantém o controle de todas essas configurações e detalhes é através de uma área mantida por ele chamada ambiente. O ambiente é uma área que o shell compila toda vez que inicia uma sessão que contém variáveis que definem propriedades do sistema.

      Neste guia, vamos discutir como interagir com o ambiente e ler ou definir variáveis de ambiente e de shell interativamente e por arquivos de configuração.

      Como o ambiente e variáveis de ambiente funcionam

      Sempre que uma sessão do shell é gerada, um processo ocorre para coletar e compilar informações que devem estar disponíveis ao processo shell e seus processos filhos. Ele obtém os dados para essas configurações de uma variedade de arquivos e configurações distintas no sistema.

      O ambiente fornece um meio pelo qual o processo shell pode obter ou definir configurações e, por sua vez, passá-las aos seus processos filhos.

      O ambiente é implementado como strings que representam pares de chave-valor. Se múltiplos valores forem passados, eles são normalmente separados por caracteres dois-pontos (:). Cada par será geralmente parecido com isto:

      KEY=value1:value2:...
      

      Se o valor contiver um espaço em branco significativo, as aspas são usadas:

      KEY="value with spaces"
      

      As chaves nesses cenários são variáveis. Elas podem ser de dois tipos, variáveis de ambiente ou variáveis de shell.

      As variáveis de ambiente são variáveis definidas para a sessão atual do shell e são herdades por qualquer shell ou processo filho. As variáveis de ambiente são usadas para passar informações para processos gerados a partir do shell.

      As variáveis de shell são variáveis contidas exclusivamente no shell no qual foram configuradas ou definidas. Geralmente, elas são usadas para manter o controle de dados efêmeros, como o diretório de trabalho atual.

      Por convenção, esses tipos de variáveis são geralmente definidos usando somente letras maiúsculas. Isso ajuda os usuários a distinguir as variáveis de ambiente em outros contextos.

      Imprimindo variáveis de ambiente e de shell

      Cada sessão do shell mantém o controle de suas variáveis de ambiente e de shell. Podemos acessá-las de algumas maneiras diferentes.

      É possível ver uma lista de todas as nossas variáveis de ambiente usando os comandos env ou printenv. Em seu estado padrão, elas devem funcionar exatamente da mesma maneira:

      Output

      SHELL=/bin/bash TERM=xterm USER=demouser LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca:... MAIL=/var/mail/demouser PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games PWD=/home/demouser LANG=en_US.UTF-8 SHLVL=1 HOME=/home/demouser LOGNAME=demouser LESSOPEN=| /usr/bin/lesspipe %s LESSCLOSE=/usr/bin/lesspipe %s %s _=/usr/bin/printenv

      Isso é algo bastante típico para o resultado tanto de printenv quanto env. A diferença entre os dois comandos só é aparente em suas funcionalidades mais específicas. Por exemplo, com printenv, é possível solicitar os valores de variáveis individuais:

      Output

      /bin/bash

      Por outro lado, o env lhe permite modificar o ambiente no qual os programas são executados passando um conjunto de definições de variável em um comando, como este:

      • env VAR1="value" command_to_run command_options

      Considerando que, assim como aprendemos acima, os processos filhos normalmente herdam as variáveis de ambiente do processo pai, isso lhe dá a oportunidade de substituir valores ou adicionar variáveis adicionais ao filho.

      Como você pode ver no resultado do nosso comando printenv, há uma quantidade razoável de variáveis de ambiente configuradas em nossos arquivos e processos de sistema sem a nossa intervenção.

      Esses comandos mostram as variáveis de ambiente, mas como vemos as variáveis de shell?

      O comando set pode ser usado para isso. Se digitarmos set sem nenhum parâmetro adicional, iremos receber uma lista de todas as variáveis de shell, variáveis de ambiente, variáveis locais e funções shell:

      Output

      BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() . . .

      Normalmente, essa é uma lista enorme. Provavelmente, é desejável canalizá-la em um programa pager para manusear mais facilmente todo o resultado:

      A quantidade de informações adicionais recebidas de volta pode parecer muito grande. Provavelmente, não é necessário conhecer todas as funções bash que estão definidas, por exemplo.

      Podemos limpar o resultado especificando que set deve operar no modo POSIX, que não irá imprimir as funções shell. Podemos executá-lo em um subshell para que ele não altere nosso ambiente atual:

      Isso irá listar todas as variáveis de ambiente e de shell que estão definidas.

      Podemos tentar comparar esse resultado com o resultado dos comandos env ou printenv para tentar obter uma lista com apenas as variáveis de shell, mas isso não será perfeito, devido às diferentes maneiras pelas quais esses comandos geram os resultados:

      • comm -23 <(set -o posix; set | sort) <(env | sort)

      Isso provavelmente ainda irá incluir algumas variáveis de ambiente, pois o comando set exibe valores entre aspas, enquanto o printenv e env não colocam os valores de strings entre aspas.

      Isso deve lhe dar uma boa noção das variáveis de ambiente e de shell que estão definidas em sua sessão.

      Essas variáveis são usadas para todo tipo de coisa. Elas oferecem uma forma alternativa de definir valores persistentes para a sessão entre processos, sem gravar alterações em um arquivo.

      Variáveis de ambiente e de shell comuns

      Algumas variáveis de ambiente e de shell são muito úteis e são referenciadas com bastante frequência. Aqui estão algumas variáveis de ambiente comuns que você deve encontrar:

      • SHELL: descreve o shell que irá interpretar todos os comandos que você digitar. Geralmente, isso será bash por padrão, mas outros valores podem ser definidos caso prefira outras opções.
      • TERM: especifica o tipo de terminal a ser emulado ao executar o shell. Diferentes terminais de hardware podem ser emulados para diferentes requisitos de operação. Normalmente, não será necessário se preocupar com isso.
      • USER: o usuário que está atualmente conectado.
      • PWD: o diretório de trabalho atual.
      • OLDPWD: o diretório de trabalho anterior. Isso é mantido pelo shell para retornar ao seu diretório anterior executando cd -.
      • LS_COLORS: define códigos de cor que são usados para adicionar um resultado de cor opcional ao comando ls. Isso é usado para distinguir diferentes tipos de arquivos e fornecer mais informações ao usuário em um olhar rápido.
      • MAIL: o caminho para a caixa de correio do usuário atual.
      • PATH: uma lista de diretórios que o sistema irá verificar ao procurar por comandos. Quando um usuário digita um comando, o sistema irá verificar diretórios neste pedido para o executável.
      • LANG: a configuração atual de idioma e localização, incluindo a codificação de caracteres.
      • HOME: o diretório base do usuário atual.
      • _: o comando executado anteriormente mais recente.

      Além dessas variáveis de ambiente, algumas variáveis de shell que você verá com frequência são:

      • BASHOPTS: a lista de opções que foram usadas quando o bash foi executado. Isso pode ser útil para descobrir se o ambiente do shell irá operar da maneira que você deseja.
      • BASH_VERSION: a versão do bash sendo executada, de forma legível por humanos.
      • BASH_VERSINFO: a versão do bash, em saída legível por máquina.
      • COLUMNS: o número de colunas de largura que estão sendo usadas para exibir um resultado na tela.
      • DIRSTACK: a pilha de diretórios que estão disponíveis com os comandos pushd e popd.
      • HISTFILESIZE: número de linhas de histórico de comando armazenadas em um arquivo.
      • HISTSIZE: número de linhas de histórico de comando permitidas na memória.
      • HOSTNAME: o nome de host do computador neste momento.
      • IFS: o separador de campo interno para separar entradas na linha de comando. Por padrão, é um espaço.
      • PS1: a de definição de prompt de comando primário. Isso é usado para definir a aparência do seu prompt quando inicia a sessão do shell. O PS2 é usado para declarar prompts secundários para quando um comando ocupa várias linhas.
      • SHELLOPTS: opções de shell que podem ser definidas com a opção set.
      • UID: o UID do usuário atual.

      Definindo variáveis de ambiente e de shell

      Para entender melhor a diferença entre as variáveis de ambiente e de shell, e para apresentar a sintaxe para definir essas variáveis, faremos uma pequena demonstração.

      Criando variáveis de shell

      Vamos começar definindo uma variável de shell dentro de nossa sessão atual. Isso é de fácil execução. Precisamos especificar apenas um nome e um valor. Vamos aderir à convenção de manter todas as letras maiúsculas para o nome da variável e defini-las em uma string simples.

      Aqui, usamos aspas, pois o valor de nossa variável contém um espaço. Além disso, usamos aspas simples, pois o ponto de exclamação é um caractere especial no bash do shell que normalmente expande para o histórico do bash se não forem colocados caracteres de escape ou colocado entre aspas simples.

      Agora, temos uma variável de shell. Essa variável está disponível em nossa sessão atual, mas não será passada para processos filhos.

      Podemos ver isso usando o grep para nossa nova variável dentro do resultado de set:

      Output

      TEST_VAR='Hello World!'

      Podemos verificar se essa não é uma variável de ambiente testando a mesma coisa com o printenv:

      Nenhum resultado deve ser retornado.

      Vamos aproveitar isso como uma oportunidade para demonstrar uma maneira de acessar o valor de qualquer variável de ambiente ou de shell.

      Output

      Hello World!

      Como você pode ver, faça referência ao valor de uma variável executando-a com um sinal de $. O shell recebe isso e entende que deve substituir o valor da variável quando se depara com isso.

      Então, agora, temos uma variável de shell. Ela não deve ser passada para nenhum processo filho. Podemos gerar um novo shell do bash de dentro do atual para demonstrar isso:

      Se digitarmos bash para gerar um shell filho e então tentarmos acessar o conteúdo da variável, nada será retornado. Isso é exatamente o que esperávamos.

      Volte para o nosso shell original digitando exit:

      Criando variáveis de ambiente

      Agora, vamos transformar nossa variável de shell em uma variável de ambiente. Podemos fazer isso exportando a variável. O comando para isso é nomeado apropriadamente:

      Isso irá alterar nossa variável para uma variável de ambiente. Podemos verificar isso olhando nossa listagem de ambiente novamente:

      Output

      TEST_VAR=Hello World!

      Desta vez, nossa variável aparece. Vamos tentar nosso experimento com o nosso shell filho novamente:

      Output

      Hello World!

      Ótimo! Nosso shell filho recebeu a variável definida pelo seu pai. Antes de sairmos deste shell filho, vamos tentar exportar outra variável. Podemos definir variáveis de ambiente em um único passo, desta forma:

      • export NEW_VAR="Testing export"

      Teste se ele foi exportado como uma variável de ambiente:

      Output

      NEW_VAR=Testing export

      Agora, vamos voltar para o nosso shell original:

      Vamos ver se nossa nova variável está disponível:

      Nada é retornado.

      Isso ocorre porque variáveis de ambiente são passadas apenas para processos filhos. Não existe uma maneira integrada de definir variáveis de ambiente do shell pai. Isso é bom na maioria dos casos e impede que os programas afetem o ambiente operacional de onde foram chamados.

      A variável NEW_VAR foi definida como uma variável de ambiente em nosso shell filho. Essa variável estaria disponível para si mesma e qualquer um de seus shells e processos filhos. Quando saímos e voltamos para o nosso shell principal, aquele ambiente foi destruído.

      Rebaixando e removendo variáveis

      Ainda temos nossa variável TEST_VAR definida como uma variável de ambiente. Podemos revertê-la para uma variável de shell digitando:

      Ela não é mais uma variável de ambiente:

      No entanto, ela ainda é uma variável de shell:

      Output

      TEST_VAR='Hello World!'

      Se quisermos remover completamente uma variável, seja ela de ambiente ou de shell, podemos fazê-lo com o comando unset:

      Podemos verificar se ela não está mais definida:

      Nada é retornado porque a variável foi removida.

      Definindo variáveis de ambiente no login

      Já mencionamos que muitos programas usam variáveis de ambiente para decidir as especificações de como operar. Não é interessante precisar definir variáveis importantes toda vez que iniciarmos uma sessão do shell. Além disso, já vimos quantas já são definidas no login. Sendo assim, como criamos e definimos variáveis automaticamente?

      Esse é realmente um problema mais complexo do que parece, devido aos inúmeros arquivos de configuração que o shell do bash lê, dependendo de como é iniciado.

      A diferença entre as sessões do shell com login, sem login, interativa e não interativa

      O shell do bash lê arquivos de configuração diferentes dependendo da forma como a sessão é iniciada.

      Uma distinção entre sessões diferentes é se o shell está sendo gerado como uma sessão com login ou sem login.

      Um shell com login é uma sessão de shell que começa pela autenticação do usuário. Se você estiver entrando em uma sessão de terminal ou via protocolo SSH e autenticar-se, sua sessão de shell será definida como um shell com login.

      Se você iniciar uma nova sessão de shell dentro de sua sessão autenticada, como fizemos chamando o comando bash do terminal, uma sessão sem login de shell será iniciada. Seus detalhes de autenticação não foram solicitados quando você iniciou seu shell filho.

      Outra distinção que pode ser feita é se uma sessão de shell é ou não interativa.

      Uma sessão de shell interativa é uma sessão que está anexada a um terminal. Uma sessão de shell não interativa é uma que não está anexada a uma sessão de terminal.

      Dessa forma, cada sessão de shell é classificada como sendo com ou sem login e interativa ou não interativa.

      Uma sessão normal que começa com o SSH é geralmente uma sessão de shell interativa com login. Um script executado a partir da linha de comando é geralmente executado em um shell não interativo e sem login. Uma sessão de terminal pode ser qualquer combinação dessas duas propriedades.

      A classificação da sessão de shell como sendo com ou sem login tem implicações sobre quais arquivos são lidos para inicializar a sessão de shell.

      Uma sessão iniciada como sessão com login lerá detalhes de configuração do arquivo /etc/profile primeiro. Em seguida, ela irá procurar pelo primeiro arquivo de configuração de shell de login no diretório base do usuário para obter detalhes de configuração específicos do usuário.

      Ela lê o primeiro arquivo que achar entre ~/.bash_profile, ~/.bash_login e ~/.profile e não lê nenhum arquivo adicional.

      Em contraste, uma sessão definida como um shell sem login lerá /etc/bash.bashrc e então o arquivo ~/.bashrc específico do usuário para compilar seu ambiente.

      Os shells não interativos leem a variável de ambiente chamada BASH_ENV e o arquivo especificado para definir o novo ambiente.

      Implementando variáveis de ambiente

      Como você pode ver, há uma grande variedade de arquivos diferentes que normalmente precisaríamos observar para colocar nossas configurações.

      Isso oferece uma grande flexibilidade que pode ajudar em situações específicas em que queremos certas configurações em um shell com login e outras configurações em um shell sem login. No entanto, na maior parte do tempo, vamos querer as mesmas configurações em ambas as situações.

      Felizmente, a maioria das distribuições Linux configuram os arquivos de configuração de login para originar os arquivos de configuração sem login. Isso significa que é possível definir as variáveis de ambiente que desejar tanto em arquivos com login, quanto nos sem login. Eles serão então lidos em ambos os cenários.

      Normalmente, vamos definir variáveis de ambiente específicas para cada usuário, e geralmente vamos querer que nossas configurações estejam disponíveis tanto em shells com login quanto sem login. Isso significa que o lugar para definir essas variáveis é no arquivo ~/.bashrc.

      Abra esse arquivo agora:

      Provavelmente, ele já irá conter uma quantidade considerável de dados. A maioria das definições aqui presentes são para definir opções do bash, que não estão relacionadas às variáveis de ambiente. É possível definir variáveis de ambiente da mesma forma que você faria da linha de comando:

      Qualquer nova variável de ambiente pode ser adicionada em qualquer lugar no arquivo ~/.bashrc, desde que não seja colocada no meio de outro comando ou loop for. Em seguida, podemos salvar e fechar o arquivo. Da próxima vez que você iniciar uma sessão do shell, sua declaração de variável de ambiente será lida e transmitida para o ambiente do shell. É possível forçar sua sessão atual a ler o arquivo agora digitando:

      Se precisar definir variáveis em todo o sistema, pense em adicioná-las ao /etc/profile, /etc/bash.bashrc ou /etc/environment.

      Conclusão

      As variáveis de ambiente e de shell estão sempre presentes em suas sessões de shell e podem ser muito úteis. Elas são uma maneira interessante para um processo pai definir detalhes de configuração para seus filhos, além de representarem uma maneira de definir opções fora dos arquivos.

      Isso oferece muitas vantagens em situações específicas. Por exemplo, a implantação de alguns mecanismos dependem de variáveis de ambiente para configurar informações de autenticação. Isso é útil, pois não requer a manutenção desses arquivos que podem ser vistos por partes externas.

      Existem muitos outros cenários, mais mundanos e comuns em que você precisará ler ou alterar o ambiente do seu sistema. Essas ferramentas e técnicas devem lhe dar uma boa base para fazer essas alterações e usá-las corretamente.



      Source link