Shell Script para WEB

 

Iniciando / Variáveis de ambiente

Iniciando

Nas configurações padrões do Apache, existe um diretório já pré-definido para scripts CGI rodarem. É o /usr/lib/cgi-bin/.

Irei criar um arquivo com o nome tutorial.sh. Nos scripts CGI, a saída dos scripts (/dev/stdout e /dev/stderr), são enviadas para o cliente, as primeiras linhas do script serão o cabeçalho de resposta da requisição HTTP.

Desse modo, podemos forçar o download de arquivos, fazer redirecionamentos, etc, a quebra de linha é que separa o que será o cabeçalho e o que será o resto da resposta.

Voltando ao arquivo tutorial.sh, dentro do arquivo, coloque as seguintes linhas:

#!/bin/bash
echo -e “Content-Type: text/plain\n”    # É o Cabeçalho, e a quebra de linha
echo “Hello World”    # Agora é o resto do request, o conteúdo que é exibido pelos navegadores.

Salve o arquivo e deixe as permissões como 775 (lembrando: r = 4, w = 2, x = 1).

Acesse o link: http://localhost/cgi-bin/tutorial.sh E verá a mensagem: Hello World

Por padrão, o Apache já configura o cabeçalho de resposta.

Se não quiser, você pode pôr no começo do script: echo -e “\n” ou printf “\n\n”, e deixar que o Apache configure o cabeçalho, que normalmente, será algo parecido com isso: 

HTTP/1.1 200 OK
Date: […]
Server: Apache […]
Content-Type: text/x-sh

Variáveis de ambiente

Em Shell Script, podemos ver quais são as variáveis de ambiente, usando o comando env. Se você digitar esse comando em um terminal, serão listadas diversas variáveis, como SHELL, HOME, USERNAME, etc.

Para listarmos as variáveis de ambiente no Apache, basta incluir no script o comando env, ficando da seguinte forma:

#!/bin/bash
echo -e “Content-Type: text/plain\n”
env

Salvei esse arquivo e acessei a página WEB usando o comando curl. O resultado, foi:

$ curl -i localhost/cgi-bin/tutorial.sh
HTTP/1.1 200 OK
Date: Tue, 25 Mar 2014 00:24:04 GMT
Server: Apache/2.2.22 (Debian)
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/plain

SERVER_SIGNATURE=

Apache/2.2.22 (Debian)
Server at localhost Port 80

HTTP_USER_AGENT=curl/7.26.0
SERVER_PORT=80
HTTP_HOST=localhost
DOCUMENT_ROOT=/var/www
SCRIPT_FILENAME=/usr/lib/cgi-bin/tutorial.sh
REQUEST_URI=/cgi-bin/tutorial.sh
SCRIPT_NAME=/cgi-bin/tutorial.sh
REMOTE_PORT=46944
PATH=/usr/local/bin:/usr/bin:/bin
PWD=/usr/lib/cgi-bin
SERVER_ADMIN=webmaster@localhost
HTTP_ACCEPT=*/*
REMOTE_ADDR=127.0.0.1
SHLVL=1
SERVER_NAME=localhost
SERVER_SOFTWARE=Apache/2.2.22 (Debian)
QUERY_STRING=
SERVER_ADDR=127.0.0.1
GATEWAY_INTERFACE=CGI/1.1
SERVER_PROTOCOL=HTTP/1.1
REQUEST_METHOD=GET
_=/usr/bin/env 

Entendendo algumas variáveis:

  • HTTP_USER_AGENT :: User-agent que o cliente está usando. Pode ser usada para pegar informações sobre quem visita a sua página (navegador e sistema operacional).
  • REQUEST_METHOD :: Método de requisição utilizado, exemplo: GET, PUT, POST, OPTIONS, HEAD. Pode ser bem útil, pelo menos para mim, já foi.
  • QUERY_STRING :: Dados enviados via GET. Exemplo: localhost/cgi-bin/tutorial.sh?a=f&b=f (sendo: a = f e b = f).
  • REMOTE_ADDR :: IP do cliente.

Exemplo de utilização de variáveis de ambiente:

#!/bin/bash

cat <<a
Content-Type: text/plain

———————————–
Seu User-agent => $HTTP_USER_AGENT
Seu I.P => $REMOTE_ADDR
———————————–
A

Testando:

$ curl localhost/cgi-bin/tutorial.sh
———————————–
Seu User-agent => curl/7.26.0
Seu I.P => 127.0.0.1
———————————– 

POST e GET / Exemplos finais

Pegando dados enviados via POST e GET

Quando trabalhamos com desenvolvimento WEB, é comum receber dados via POST e/ou GET. Começarei com o GET, para POST, é praticamente a mesma coisa, só muda mesmo quando se faz upload de arquivos.

Em bash script, a variável IFS funciona como uma função split. Colocamos o que será delimitado, a variável seguinte se transforma em um vetor. Depois, usando o laço for, podemos extrair os campos e valores respectivos enviados via GET:

d#!/bin/bash echo -e “\n”
IFS=’=&’
GET=($QUERY_STRING)

for ((i=0; i<${#GET[@]}; i+=2))
do
echo “${GET[@]:$i:1} = ${GET[@]:$i+1:1}”
done

Testando:

$ curl ‘localhost/cgi-bin/tutorial.sh?teste=ffff&teste2=xxxxx’
 teste = ffff
teste2 = xxxxx 

Com POST, a única diferença é que não existe uma variável de ambiente com os valores. Para obter esses valores, basta o seguinte comando: read variavel

Os dados enviados via POST ficam em /dev/stdin, por isso, quando utilizamos o read, esses valores são obtidos. Feito isso, é só trocar o GET por POST:

#!/bin/bash
echo -e “\n”
read var
IFS=’=&’
POST=($var)

for ((i=0; i<${#POST[@]}; i+=2))
do
echo “${POST[@]:$i:1} = ${POST[@]:$i+1:1}”
done

Testando:

$ curl localhost/cgi-bin/tutorial.sh –data “autor=mmxm&blog=hc0der.blogspot.com”
 autor = mmxm
blog = hc0der.blogspot.com 

Exemplos finais

Alguns exemplos que podem ser úteis (hehe).

Redirecionamento, usando header:

#!/bin/bash

printf “Status: 302 Found\n”
printf “Location: http://hc0der.blogspot.com\n\n”;

Testando:

$ curl localhost/cgi-bin/tutorial.sh -i
HTTP/1.1 302 Found
Date: Wed, 26 Mar 2014 00:01:08 GMT
Server: Apache/2.2.22 (Debian)
Location: http://hc0der.blogspot.com
Content-Length: 0
Content-Type: text/x-sh 

Falso “404 not found”:

#!/bin/bash

printf “Status: 404 Not Found\n\n”

Testando:

$ curl localhost/cgi-bin/tutorial.sh -i
HTTP/1.1 404 Not Found
Date: Wed, 26 Mar 2014 00:06:53 GMT
Server: Apache/2.2.22 (Debian)
Content-Length: 0
Content-Type: text/x-sh 

Fazendo download de arquivos:

#!/bin/bash

arquivo_local=/etc/issue stat -c “Content-Length: %s” $arquivo_local # enviar tamanho do arquivo em bytes
printf “Content-Disposition: attachment; filename=$(basename $arquivo_local)\n”
printf “Content-Type: application/octet-stream\n\n”
cat $arquivo_local

Testando:

$ curl localhost/cgi-bin/tutorial.sh -i
HTTP/1.1 200 OK
Date: Wed, 26 Mar 2014 00:13:32 GMT
Server: Apache/2.2.22 (Debian)
Content-Disposition: attachment; filename=issue
Content-Length: 17
Vary: Accept-Encoding
Content-Type: application/octet-stream

nao te interessa 

E, via browser:

Linux: Shell Script para WEB

Conclusão

Para uma introdução, está de bom tamanho. Bash Script é complicado, conhecendo bem as ferramentas do seu sistema, não há limites para o que você pode fazer =>.

Rolar para cima