Usando expressões regulares no bash

Exemplo prático. Validando endereço de IP:

if [[ $IP_ADDR =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then
        echo "IP Valido"
else
	echo "IP Invalido"
fi

Para negar a validação

if [[ ! $IP_ADDR =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]; then
        echo "IP Invalido"
else
	echo "IP Valido"
fi

Compiling mod_rpaf on Apache 2.4

Another module with error in make command and more patches to do…

[13:02:59 root@template-centos-6-2 mod_rpaf-0.6]# /usr/local/apache2/bin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c
/usr/local/apache2/build/libtool --silent --mode=compile gcc -std=gnu99 -prefer-pic   -D_REENTRANT -D_GNU_SOURCE -g -O2 -pthread -I/usr/local/apache2/include  -I/usr/local/apache2/include   -I/usr/local/apache2/include   -c -o mod_rpaf-2.0.lo mod_rpaf-2.0.c && touch mod_rpaf-2.0.slo
mod_rpaf-2.0.c: In function 'rpaf_cleanup':
mod_rpaf-2.0.c:150: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c:151: error: 'conn_rec' has no member named 'remote_addr'
mod_rpaf-2.0.c:151: warning: implicit declaration of function 'inet_addr'
mod_rpaf-2.0.c:151: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c: In function 'change_remote_ip':
mod_rpaf-2.0.c:164: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c:183: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c:186: error: 'conn_rec' has no member named 'remote_ip'
mod_rpaf-2.0.c:187: error: 'conn_rec' has no member named 'remote_addr'
mod_rpaf-2.0.c:187: error: 'conn_rec' has no member named 'remote_ip'
apxs:Error: Command failed with rc=65536

Below, the full source of patched mod_rpaf-2.0.c that works on apache 2.4

/* ====================================================================
 * Copyright (c) 1995 The Apache Group.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * 4. The names "Apache Server" and "Apache Group" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission.
 *
 * 5. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
 * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Group and was originally based
 * on public domain software written at the National Center for
 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
 * For more information on the Apache Group and the Apache HTTP server
 * project, please see <http://www.apache.org/>.
 *
 */

/*
 * $Id: mod_rpaf-2.0.c 18 2008-01-01 03:05:40Z thomas $
 *
 * Author: Thomas Eibner, <[email protected]>
 * URL: http://stderr.net/apache/rpaf/
 * rpaf is short for reverse proxy add forward
 *
 * This module does the opposite of mod_proxy_add_forward written by
 * Ask Bjørn Hansen. http://develooper.com/code/mpaf/ or mod_proxy
 * in 1.3.25 and above and mod_proxy from Apache 2.0
 *
 */

#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_vhost.h"
#include "apr_strings.h"

module AP_MODULE_DECLARE_DATA rpaf_module;

typedef struct {
    int                enable;
    int                sethostname;
    const char         *headername;
    apr_array_header_t *proxy_ips;
} rpaf_server_cfg;

typedef struct {
    const char  *old_ip;
    request_rec *r;
} rpaf_cleanup_rec;

static void *rpaf_create_server_cfg(apr_pool_t *p, server_rec *s) {
    rpaf_server_cfg *cfg = (rpaf_server_cfg *)apr_pcalloc(p, sizeof(rpaf_server_cfg));
    if (!cfg)
        return NULL;

    cfg->proxy_ips = apr_array_make(p, 0, sizeof(char *));
    cfg->enable = 0;
    cfg->sethostname = 0;

    return (void *)cfg;
}

static const char *rpaf_set_proxy_ip(cmd_parms *cmd, void *dummy, const char *proxy_ip) {
    server_rec *s = cmd->server;
    rpaf_server_cfg *cfg = (rpaf_server_cfg *)ap_get_module_config(s->module_config,
                                                                   &rpaf_module);

    /* check for valid syntax of ip */
    *(char **)apr_array_push(cfg->proxy_ips) = apr_pstrdup(cmd->pool, proxy_ip);
    return NULL;
}

static const char *rpaf_set_headername(cmd_parms *cmd, void *dummy, const char *headername) {
    server_rec *s = cmd->server;
    rpaf_server_cfg *cfg = (rpaf_server_cfg *)ap_get_module_config(s->module_config,
                                                                   &rpaf_module);

    cfg->headername = headername;
    return NULL;
}

static const char *rpaf_enable(cmd_parms *cmd, void *dummy, int flag) {
    server_rec *s = cmd->server;
    rpaf_server_cfg *cfg = (rpaf_server_cfg *)ap_get_module_config(s->module_config,
                                                                   &rpaf_module);

    cfg->enable = flag;
    return NULL;
}

static const char *rpaf_sethostname(cmd_parms *cmd, void *dummy, int flag) {
    server_rec *s = cmd->server;
    rpaf_server_cfg *cfg = (rpaf_server_cfg *)ap_get_module_config(s->module_config,
                                                                   &rpaf_module);

    cfg->sethostname = flag;
    return NULL;
}

static int is_in_array(const char *remote_ip, apr_array_header_t *proxy_ips) {
    int i;
    char **list = (char**)proxy_ips->elts;
    for (i = 0; i < proxy_ips->nelts; i++) {
        if (strcmp(remote_ip, list[i]) == 0)
            return 1;
    }
    return 0;
}

static apr_status_t rpaf_cleanup(void *data) {
    rpaf_cleanup_rec *rcr = (rpaf_cleanup_rec *)data;
    rcr->r->connection->client_ip   = apr_pstrdup(rcr->r->connection->pool, rcr->old_ip);
    rcr->r->connection->client_addr->sa.sin.sin_addr.s_addr = apr_inet_addr(rcr->r->connection->client_ip);
    return APR_SUCCESS;
}

static int change_remote_ip(request_rec *r) {
    const char *fwdvalue;
    char *val;
    rpaf_server_cfg *cfg = (rpaf_server_cfg *)ap_get_module_config(r->server->module_config,
                                                                   &rpaf_module);

    if (!cfg->enable)
        return DECLINED;

    if (is_in_array(r->connection->client_ip, cfg->proxy_ips) == 1) {
        /* check if cfg->headername is set and if it is use
           that instead of X-Forwarded-For by default */
        if (cfg->headername && (fwdvalue = apr_table_get(r->headers_in, cfg->headername))) {
            //
        } else if (fwdvalue = apr_table_get(r->headers_in, "X-Forwarded-For")) {
            //
        } else {
            return DECLINED;
        }

        if (fwdvalue) {
            rpaf_cleanup_rec *rcr = (rpaf_cleanup_rec *)apr_pcalloc(r->pool, sizeof(rpaf_cleanup_rec));
            apr_array_header_t *arr = apr_array_make(r->pool, 0, sizeof(char*));
            while (*fwdvalue && (val = ap_get_token(r->pool, &fwdvalue, 1))) {
                *(char **)apr_array_push(arr) = apr_pstrdup(r->pool, val);
                if (*fwdvalue != '')
                    ++fwdvalue;
            }
            rcr->old_ip = apr_pstrdup(r->connection->pool, r->connection->client_ip);
            rcr->r = r;
            apr_pool_cleanup_register(r->pool, (void *)rcr, rpaf_cleanup, apr_pool_cleanup_null);
            r->connection->client_ip = apr_pstrdup(r->connection->pool, ((char **)arr->elts)[((arr->nelts)-1)]);
            r->connection->client_addr->sa.sin.sin_addr.s_addr = apr_inet_addr(r->connection->client_ip);
            if (cfg->sethostname) {
                const char *hostvalue;
                if (hostvalue = apr_table_get(r->headers_in, "X-Forwarded-Host")) {
                    /* 2.0 proxy frontend or 1.3 => 1.3.25 proxy frontend */
                    apr_table_set(r->headers_in, "Host", apr_pstrdup(r->pool, hostvalue));
                    r->hostname = apr_pstrdup(r->pool, hostvalue);
                    ap_update_vhost_from_headers(r);
                } else if (hostvalue = apr_table_get(r->headers_in, "X-Host")) {
                    /* 1.3 proxy frontend with mod_proxy_add_forward */
                    apr_table_set(r->headers_in, "Host", apr_pstrdup(r->pool, hostvalue));
                    r->hostname = apr_pstrdup(r->pool, hostvalue);
                    ap_update_vhost_from_headers(r);
                }
            }

        }
    }
    return DECLINED;
}

static const command_rec rpaf_cmds[] = {
    AP_INIT_FLAG(
                 "RPAFenable",
                 rpaf_enable,
                 NULL,
                 RSRC_CONF,
                 "Enable mod_rpaf"
                 ),
    AP_INIT_FLAG(
                 "RPAFsethostname",
                 rpaf_sethostname,
                 NULL,
                 RSRC_CONF,
                 "Let mod_rpaf set the hostname from X-Host header and update vhosts"
                 ),
    AP_INIT_ITERATE(
                    "RPAFproxy_ips",
                    rpaf_set_proxy_ip,
                    NULL,
                    RSRC_CONF,
                    "IP(s) of Proxy server setting X-Forwarded-For header"
                    ),
    AP_INIT_TAKE1(
                    "RPAFheader",
                    rpaf_set_headername,
                    NULL,
                    RSRC_CONF,
                    "Which header to look for when trying to find the real ip of the client in a proxy setup"
                    ),
    { NULL }
};

static void register_hooks(apr_pool_t *p) {
    ap_hook_post_read_request(change_remote_ip, NULL, NULL, APR_HOOK_FIRST);
}

module AP_MODULE_DECLARE_DATA rpaf_module = {
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    rpaf_create_server_cfg,
    NULL,
    rpaf_cmds,
    register_hooks,
};

Hope it helps ^^

Compiling mod_jk on apache 2.4

Sorry for brazilian users that cant read it, but at this time, i will post in english, because this can help everyone to solve this problem.

Im was trying to compile mod_jk on the lastest version of apache (2.4) and get this error on “make”

Making all in apache-2.0
make[1]: Entering directory `/usr/local/install/Java-packages/tomcat-connectors-1.2.32-src/native/apache-2.0′
/usr/local/apache2/build/libtool –silent –mode=compile gcc -std=gnu99 -I/usr/local/apache2/include  -DHAVE_CONFIG_H -DUSE_APACHE_MD5 -I ../common -I /usr/java/j2sdk//include -I /usr/java/j2sdk//include/unix -D_REENTRANT -D_GNU_SOURCE -g -O2 -pthread -DHAVE_APR  -I/usr/local/apache2/include -I/usr/local/apache2/include  -DHAVE_CONFIG_H -g -O2 -pthread -D_REENTRANT -D_GNU_SOURCE -c mod_jk.c -o mod_jk.lo
mod_jk.c: In function ‘init_ws_service’:
mod_jk.c:767: error: ‘conn_rec’ has no member named ‘remote_ip’
mod_jk.c:768: error: ‘conn_rec’ has no member named ‘remote_addr’
mod_jk.c:1036: error: ‘conn_rec’ has no member named ‘remote_ip’
mod_jk.c:1036: error: ‘conn_rec’ has no member named ‘remote_ip’
make[1]: *** [mod_jk.lo] Error 1

Reading the API documentation i found the solution.

the file apache-2.0/mod_jk.c uses conn_rec->remote_ip and conn_rec->remote_addr that was discontinued on the new API

For a perfect compilation, edit apache-2.0/mod_jk.c file and change the lines below:

Line 767:

Before:
s->remote_addr = r->connection->remote_ip;
After (with patch):
s->remote_addr = r->connection->client_ip;

Line 768:

Before:
s->remote_port = apr_itoa(r->pool, r->connection->remote_addr->port);
After:
s->remote_port = apr_itoa(r->pool, r->connection->client_addr->port);

Line 1036:

Before:
STRNULL_FOR_NULL(r->connection->remote_ip),
After:
STRNULL_FOR_NULL(r->connection->client_ip),

Now, the “make” command can run perfect! 😉

Usando vários núcleos no make

Dica do Cifali

make -j17

aonde 17 é a quantidade de núcleos+1 que deseja usar na compilação. nesse caso usamos 16 nucleos, ou seja, se a maquian que  for compilar tiver 4 núcleos, usar -j5

OBS: Na documentação do make não recomendam usar essa opção, mas até agora não tivemos problemas neste quesito.
OBS2: Isso aumenta consideravelmente o load do servidor, então cuidado!

Encontrando arquivos que foram modificados nos ultimos 15 minutos

Sempre me perguntei como os empacotadores de rpm deb compilavam as coisas e depois faziam o pacote com os binários/libs pré-compilados

Depois de uma longa pesquisa no gooogle aliado a uma boa leitura do man/help descobri um comando que pode ser muito útil.

Basicamente eu baixo os tar.gz do que eu quero instalar (ex. nginx) descompacto, compilo com as infos que eu quero, depois executo o comando abaixo para verificar quais arquivos foram modificados nos últimos 15 minutos. Para um resultado mais preciso, basta cronometrar quanto tempo levou o make install e ajustar no comando conforme necessidade.

find / -type f -mmin -15 |egrep -v "^/proc|^/home|^/root|^/.|^/tmp|.log$"

Esse egrep serve pra filtar o conteúdo que não é desejado, por exemplo: Não me importa se houve modificações no /proc ou /tmp

Lista de if em shellscript

Neste exemplo estou usando o comando test, mas pode ser com if também

test ­-r #Testa se tem permissão de leitura
test ­-w #Testa se tem permissão de escrita
test ­-x #Testa se tem permissão de execução
test ­-f #Testa se é um arquivo regular
test ­-d #Testa se é um diretório
test ­-u #Testa se seu SUID está ativado
test ­-g #Testa se seu SGID está ativado
test ­-s #Testa se seu tamanho é maior que zero

Exemplo:
Exibe o texto “ok” se o arquivo teste.txt possuir permissão de leitura:

test -r teste.txt && echo "ok"

Da pra usar os mesmos parametros usando IF:

if [ -r teste.txt ]; then echo "ok"; fi

Negação (exibe a mensagem se não tiver permissão de escrita):

test -r teste.txt || echo "nao ok"