Centos: deshabilitar comando

Tuvimos un problema con el comando yarn, ya que había un bug y era inevitable que los usuarios sigan usando este comando, entonces la solución sería deshabilitarlo, para esto es necesario editar o crear el siguiente archivo:

/etc/profile.d/local.sh

Con el siguiente contenido

alias 'yarn=echo "command disabled..."'

Y listo eso es todo

CentOS 7: Read-only file system

Repentinamente todo el SO esta en modo escritura, una de las razones esta relacionado a procesos (Inodes) huérfanos. Cabe mencionar que no tenemos acceso directo al servidor, solo de manera remota.

Intentamos crear un archivo para verificar:

# touch test.txt
touch: cannot touch ‘test.txt’: Read-only file system

Revisamos los mensajes del diagnostico:

# dmesg
[83074.909312] systemd-journald[781]: Failed to write entry (21 items, 613 bytes), ignoring: Read-only file system

Intentamos reparar los errores con fsck

# fsck -f /dev/md4
fsck from util-linux 2.23.2
e2fsck 1.42.9 (28-Dec-2013)
/dev/md4 has unsupported feature(s): metadata_csum
e2fsck: Get a newer version of e2fsck!

Procedemos a iniciar con una version de rescate, en este caso Debian y revisamos las particiones

rescue:~# fdisk -l
Disk /dev/ram0: 640 MiB, 671088640 bytes, 1310720 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes

Disk /dev/nvme0n1: 894.3 GiB, 960197124096 bytes, 1875385008 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: C836E485-806C-42EE-8078-4279D377AB7D

Device Start End Sectors Size Type
/dev/nvme0n1p1 2048 6143 4096 2M BIOS boot
/dev/nvme0n1p2 6144 3905535 3899392 1.9G Linux RAID
/dev/nvme0n1p3 3905536 11718655 7813120 3.7G Linux swap
/dev/nvme0n1p4 11718656 1875382271 1863663616 888.7G Linux RAID

Disk /dev/nvme1n1: 894.3 GiB, 960197124096 bytes, 1875385008 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 61048823-5D74-4375-853B-7D0C6EF32E33

Device Start End Sectors Size Type
/dev/nvme1n1p1 2048 6143 4096 2M BIOS boot
/dev/nvme1n1p2 6144 3905535 3899392 1.9G Linux RAID
/dev/nvme1n1p3 3905536 11718655 7813120 3.7G Linux swap
/dev/nvme1n1p4 11718656 1875382271 1863663616 888.7G Linux RAID

Disk /dev/md127: 888.7 GiB, 954195574784 bytes, 1863663232 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/md126: 1.9 GiB, 1996423168 bytes, 3899264 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Seguidamente intentamos reparar las particiones fisicas:

  • /dev/md126
rescue:~# fsck -f /dev/md126
fsck from util-linux 2.29.2
e2fsck 1.43.4 (31-Jan-2017)
boot: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
boot: 350/121920 files (14.0% non-contiguous), 52021/487408 blocks
  • /dev/md127
rescue:~# fsck -f /dev/md127
fsck from util-linux 2.29.2
e2fsck 1.43.4 (31-Jan-2017)
root: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Inodes that were part of a corrupted orphan linked list found. Fix? yes
Inode 54264123 was part of the orphaned inode list. FIXED.
Inode 54264340 was part of the orphaned inode list. FIXED.
Inode 54264511 was part of the orphaned inode list. FIXED.
Inode 54265536 was part of the orphaned inode list. FIXED.
Deleted inode 54266256 has zero dtime. Fix? yes
root: FILE SYSTEM WAS MODIFIED
root: 968153/58245120 files (0.8% non-contiguous), 47404979/232957904 blocks

Finalmente procedemos a reiniciar el SO de manera normal.

CentOS: llamadas sobre SSL

Se tienen los certificados:

  • ssl.key (privada)
  • ssl.cert (publica)
  • ca.cert
  • pass phrase

La llave publica ssl.cert, esta instalada en el servidor DEVIL.

Se necesita enviar un json mediante POST desde el servidor HOST (Centos7) a DEVIL (SAP) sobre SSL, esto implica enviar las llaves publica, privada a demás de tener una validación del certificado CA y el pass phrase.

Si se envía los datos por curl de esta manera:

curl -v --cert ./ssl.cert --key ./ssl.key --cacert ./ca.cert --header "Content-Type: application/json" --data '{"key":"value"}' https://devil.com/

Obtendríamos una respuesta como esta:

About to connect() to devil.com port 443 (#0)
Trying 123.123.123.123…
Connected to devil.com (123.123.123.123) port 443 (#0)
Initializing NSS with certpath: sql:/etc/pki/nssdb
CAfile: ca.cert
CApath: none
Server certificate:
subject: CN=…………………………………..
start date: Jan 22 00:00:00 2020 GMT
expire date: Jan 22 12:00:00 2022 GMT
common name: *…………………………………
issuer: CN=……………………………………
NSS error -8172 (SEC_ERROR_UNTRUSTED_ISSUER)
Peer's certificate issuer has been marked as not trusted by the user.
Closing connection 0
curl: (60) Peer's certificate issuer has been marked as not trusted by the user.
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.

Haciendo la misma llamada de manera insegura, agregando la opción -k:

curl -v -k --cert ./ssl.cert --key ./ssl.key --cacert ./ca.cert --header "Content-Type: application/json" --data '{"key":"value"}' https://devil.com/

La respuesta seria algo así:

About to connect() to devil.com port 443 (#0)
Trying 123.123.123.123…
Connected to devil (123.123.123.123) port 443 (#0)
Initializing NSS with certpath: sql:/etc/pki/nssdb
skipping SSL peer certificate verification
NSS: client certificate from file
subject: CN=…………………………………………………..
start date: May 22 00:00:00 2020 GMT
expire date: Feb 10 12:00:00 2021 GMT
common name: ………………………………………………….
issuer: CN=…………………………………………………
SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Server certificate:
subject: CN=*………………………………………………….
start date: Jan 22 00:00:00 2020 GMT
expire date: Jan 22 12:00:00 2022 GMT
common name: *…………………………………………………
issuer: CN=……………………………………………………
POST /http/Orders HTTP/1.1
User-Agent: curl/7.29.0
Host: devil.com
Accept: /
Content-Type: application/json
Content-Length: 664
upload completely sent off: 664 out of 664 bytes
< HTTP/1.1 401
< X-message-code: PWD_WRONG
< WWW-Authenticate: Basic realm="SAP HANA Cloud Platform"
< Transfer-Encoding: chunked
< Date: Thu, 28 May 2020 19:32:54 GMT
< Server: SAP
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
<
Connection #0 to host devil.com left intact

Un detalle si se usa la opción -k los parámetros cacert y capath dejan de funcionar

Bien la solución es instalar(copiar) el certificado ca.cert, de la siguiente manera:

cp ca.cert /etc/pki/ca-trust/source/anchors/
update-ca-trust extract

Con esto la llamada de forma segura (sin el parámetro -k ) y sin el certificado CA debería ser exitosa.

curl -v --cert ./ssl.cert --key ./ssl.key --header "Content-Type: application/json" --data '{"key":"value"}' https://devil.com/

Este problema también afecta a las llamadas curl que se hacen desde PHP

Android: fallan las conexiones

Vamos indicando el entorno, se tiene una app en Android y que hace llamadas de tipo POST a un servidor para obtener datos, el servidor cuenta con SO Centos 6, apache, php 5.6, mysql, un servidor normal.

Lo que sucede, se tiene varios dispositivos de la misma red (6 dispositivos) trabajando con la app al mismo tiempo, cuando ingresa uno nuevo suceden dos cosas.

  • El ultimo simplemente deja de recibir la informacion del servidor por medio de la app.
  • Todas se bloquean excepto el primer dispositivo que uso la app.

Los mensajes de error en adroid son los siguientes:

org.apache.http.conn.HttpHostConnectException: Connection to https://xxx.com/ refused
java.net.SocketTimeoutException: failed to connect to xxx.com/111.222.333.444 (port 443) after 3000ms

La solucion en este caso fue desactivar el TCP timestamps de centos.

echo "0" > /proc/sys/net/ipv4/tcp_timestamps

CentOS: «daemonizar» scripts PHP

Un problema con el que estuve sufriendo peleando por un buen rato fue el de tener scripts PHP funcionando todo el tiempo.

El problema era que no se podía usar cronjobs, ya que los scripts funcionaban con gearman (del cual escribiré en otro post) y tenían que estar a la espera de ser invocados y realizar una determinada tarea, la cual tiene un tiempo variable y por tanto no se puede usar cron.

Las características debían ser de poder iniciar los scripts PHP y tenerlos como servicios o demonios, a demás de poder pararlos en cualquier momento, generalmente para hacer alguna modificación.

Después de buscar por un rato llegue con estas dos soluciones:

  1. Usar System_Daemon.
  2. Usar Supervisor.

Obviamente ninguna de las dos formas funciono, la verdad es que no pude instalar ninguno de ellos (por problemas de dependencias, alertas, etc). Entonces la solución sería hacer uno mismo el script, y aquí lo tenemos:

#!/bin/sh
# description: start php script

. /etc/rc.d/init.d/functions

pathworker=/home/user/public_html/script.php

start() {
        echo -n "Starting script"
        daemon php "$pathworker&"
}

stop() {
        echo -n "Stopping script"
        killproc php "$pathworker"
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    *)
        echo $"Usage: $prog {start|stop|restart}"
esac

Es claro que el script es bastante sencillo pero cumple con su función y eso es lo importante, supongamos que lo llamamos phpd, tiene que estar en /etc/init.d. Claro antes tiene que tener permisos de ejecución:

sudo chmod +x /etc/init.d/phpd

Para iniciar el demonio:

/etc/init.d/phpd start

Para pararlo:

/etc/init.d/phpd stop

Y eso sería prácticamente todo, ahora si se quiere daemonizar varios scripts PHP a la vez se puede modificar el script quedando de la siguiente manera:

#!/bin/sh
# description: start php script

. /etc/rc.d/init.d/functions

pathworker=/home/user/public_html/list

start() {
        echo -n "Starting script"
        daemon "$pathworker&"
}

stop() {
        echo -n "Stopping script"
        killproc php "$pathworker"
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    *)
        echo $"Usage: $prog {start|stop|restart}"
esac

Donde el archivo list contendría los scripts PHP que se desean daemonizar:

#!/bin/sh
php /home/user/public_html/script1.php &&
php /home/user/public_html/script2.php &&
php /home/user/public_html/script3.php;

Nota: al hacer esto hay un problema y es que no se pueden parar todos los demonios iniciados con el comando stop, si no que habría que hacerlo manualmente.