Eventos

TDC 2012: slides e demo da palestra

Na edição Goiânia que acontenceu nos dias 20 e 21 de Outubro participei da trilha Java com a paelstra “Aumentando a eficiência do web container com chamadas assíncronas“.

Após um longo tempo finalmente tive tempo de disponibilizar a demo no github.

Os slides estão disponíveis no slideshare.

 

O projeto usado na demo está disponível no Github no repositório TDC2012-asyncservlets.

Abraço.

Dicas

Bash Script: substituindo um texto em vários arquivos

Neste post quero compartilhar um bash script que criei para um necessidade bastante comum em ambientes Unix Like.

Necessidade:

“alterar um texto em vários arquivos de uma única vez”

Situação hipotética:

“vários arquivos texto (xml, properties, txt etc) espalhados dentro de um diretório raiz contendo um determinado termo (palavra, path de arquivo, propriedade etc)”

Esse tipo de situação é bastante comum no dia a dia de um administrador de sistemas e servidores. A abordagem da utilização de um script para automatizar esse tipode tarefa é bastante utilizada em ambientes baseados em Unix que possuam um shell com suporte a qualquer linguagem de script (bash, ksh, python, ruby etc).

No meu caso implementei um script bash para execução em sistemas Linux. Minha necessidade inicial foi alterar o caminho da instalação do Oracle Weblogic Application Server – WLS. A instalação do WLS escreve o caminho do diretório raiz da instalação em vários arquivos de configuração (arquivos .properties e .xml) e scripts de gerenciamento (arquivos .sh) espalhados por toda a sua estrutura de diretórios. Caso seja necessário alterar o caminho raiz da instalação do WLS, você tem duas alternativas: 1) instalar novamente o WLS; 2) alterar o path da instalação em todos os arquivos de configuração.

No meu caso meu WLS foi instalado em ‘/opt/Oracle/Middleware‘, porém precisei mudar o caminho raiz para ‘/opt/Oracle/Middlware11g.

Pois bem, meu scritpt recebe como entrada os seguintes parâmetros:

  1. path: diretório raiz onde os arqivos se encontram
  2. file pattern name: nome do arquivo a ser alterado (geralmente um coringa ‘*.’)
  3. old text: texto a ser alterado
  4. new text: novo texto

Quando executar o script sem parâmetros um pequeno help será exibido sugerindo um exemplo de uso.

# ~/replaceText.sh
invalid call!
 usage: ./replaceText <path> <file pattern name> <old text> <new text>
NOTES:
 1) don't use the pattern '*', instead specify a file extension (eg: '*.sh', '*.txt', '*.properties', '*.xml')
 2) for text containing special chars you have to scape them with '\'
eg: ./replaceText "/opt/Oracle/Middleware" "*.xml" "Oracle\/Middleware\/" "Oracle\/Middleware11g\/"

Ao executar o script com todos os parâmetros o diretório raiz (primeiro argumento) será percorrido e, para cada arquivo encontrado (obedecendo o padrão informado no segundo argumento), será necessário confirmar a alteração.

# ~/replaceText.sh /opt/Oracle/Middleware/ "*.properties" "Oracle\/Middleware\/" "Oracle\/Middleware11g\/"
 alterar o arquivo: /opt/Oracle/Middleware/user_projects/domains/cluster-replicated-domain/init-info/tokenValue.properties
 deseja continuar? ([S]im/[n]ao/[t]odos) S
 substituir [Oracle\/Middleware\/] por [Oracle\/Middleware11g\/]
 diff /opt/Oracle/Middleware/user_projects/domains/cluster-replicated-domain/init-info/tokenValue.properties /opt/Oracle/Middleware/user_projects/domains/cluster-replicated-domain/init-info/tokenValue.properties.BAK
 ----------------------------------------
 21c21
 < @DOMAIN_HOME=/opt/Oracle/Middleware11g/user_projects/domains/cluster-replicated-domain
 ---
 > @DOMAIN_HOME=/opt/Oracle/Middleware/user_projects/domains/cluster-replicated-domain
 24c24
 < @USERDOMAIN_HOME=/opt/Oracle/Middleware11g/user_projects/domains/cluster-replicated-domain
 ---
 > @USERDOMAIN_HOME=/opt/Oracle/Middleware/user_projects/domains/cluster-replicated-domain
 ----------------------------------------

No exemplo acima alterei todos os arquivos de propriedades (*.properties). Observe que existe a opção de alterar todos os arquivos encontrados de uma única vez. Basta selecionar a opção [a]ll quando for solicitada a confirmação. Observe também que o script faz um backup de todos os arquivos alterados (.BAK).

Ok. Após todo esse bla bla bla o código do script:

#!/bin/bash

DIR_PATH=$1
FILE_SEARCH_PATTERN=$2
OLD_STRING=$3
NEW_STRING=$4

LAST_REPLY="S"

askToContinue(){
   if [[ ! $LAST_REPLY =~ ^[Aa]$  ]]
   then
      read -p "continue? ([Y]es/[n]o/[A]ll) " -n1
      echo

      LAST_REPLY=$REPLY
      if [[ ! $REPLY =~ ^[Yy]$ ]]
      then
         continue
      fi
   fi
}

usage(){
   echo
   echo -e "\r invalid call!"
   echo -e "   usage: ./replaceText    "
   echo
   echo -e "\r NOTES:"
   echo -e "\r\t 1) don't use the pattern '*', instead specify a file extension (eg: '*.sh', '*.txt', '*.properties', '*.xml')"
   echo -e "\r\t 2) for text containing special chars you have to scape them with '\'"
   echo
   echo -e "   eg: ./replaceText \"/opt/Oracle/Middleware\" \"*.xml\" \"Oracle\\/Middleware\\/\" \"Oracle\\/Middleware11g\\/\""
   echo
   exit
}

[[ ! "$#" = "4" ]] && usage

for file_name in `find "$DIR_PATH" -type f -name "$FILE_SEARCH_PATTERN"`
do
  #Testa se o arquivo contem o texto a ser substituido
  file $file_name | grep -i "text" > /dev/null
  [[ "$?" -eq "1"  ]] && continue
  grep $OLD_STRING $file_name > /dev/null
  [[ "$?" -eq "1"  ]] && continue

  echo -e "\r\r\r changes the file: $file_name \r"
  askToContinue

  echo -e "\t replace [$OLD_STRING] by [$NEW_STRING] \r"

  if [ -d $DIR_PATH  ];
  then
     sed -i.BAK -e "s/${OLD_STRING}/${NEW_STRING}/g" $file_name

     echo -e "\t\t diff $file_name $file_name.BAK"
     echo -e "\r ----------------------------------------"
     diff $file_name $file_name.BAK
     echo -e "\r ----------------------------------------"
  else
     echo -e "\r $PATH_DIR does not exists!"
     exit
  fi

done

Eu usei o script sem problemas em um Linux Fedora (Linux Red Hat based). Mas creio que funcionará sem grandes problemas em qualquer Unix com um shell Bash.

Abraço 😉