Skip to content

Instantly share code, notes, and snippets.

@edwrodrig
Last active February 1, 2024 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edwrodrig/60c3fdc1bf015fa2f59c to your computer and use it in GitHub Desktop.
Save edwrodrig/60c3fdc1bf015fa2f59c to your computer and use it in GitHub Desktop.
interface abstraction layer vs direct usage

Última actualización: 2024-02-01

This is an example to show the power of gcc optimizer. It can generate almost the same Assembly for either a general object oriented abstracted code and the simplest way to do the same thing.

Versión de compilador

g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.9.2-10ubuntu13' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.2 (Ubuntu 4.9.2-10ubuntu13)

simplest.cpp

int queryBudgetAmountById(int id);

int queryStuffPriceById(int id);

bool accept(int idBudget, int idStuff) {
  auto budgetAmount = queryBudgetAmountById(idBudget);
  auto stuffPrice = queryStuffPriceById(idStuff);
  return stuffPrice <= budgetAmount;
}

nicest.cpp

//Ugly unavoidable database interface
int queryBudgetAmountById(int id);

int queryStuffPriceById(int id);

//We build a type safe templated Id class
template<class T>
class Id {
  public:
    int val;
    int unused;
    Id(int v) : val{v} {;}
    operator int() const { return val; }
};

//A type safe money class
class Money {
  public:
    int val;
    int unused;
    Money(int v) : val{v}, unused() {;}
    bool operator<=(const Money& m) const { return val <= m.val; }
};


//Our database entities
class Entity {
  int unused;
};

class Stuff : public Entity {
  public:
    using Id = ::Id<Stuff>;
    int yet_another_unused;
    Money price;
    Stuff(const Money& p) : price{p} {;}
};

class Budget : public Entity {
  public:
    using Id = ::Id<Budget>;
    int more_unused;
    Money amount;
    Budget(const Money& a) : amount{a} {;}
    bool canAfford(const Stuff& s) const { return s.price <= amount; }
};


//It's better to resolve functions by type than by function name
inline Budget get(const Budget::Id& id) {
  auto money = queryBudgetAmountById(id);
  return Budget{money};
}

inline Stuff get(const Stuff::Id& id) {
  auto money = queryStuffPriceById(id);
  return Stuff{money};
}

//Really nice usage
bool accept(int idBudget, int idStuff) {
  auto budget = get(Budget::Id{idBudget});
  auto stuff = get(Stuff::Id{idStuff});
  return budget.canAfford(stuff);
}

simplest.asm

Salida de

g++ -std=c++11 simplest.cpp -o simplest.asm -O3 -S
	.file	"simplest.cpp"
	.section	.text.unlikely,"ax",@progbits
.LCOLDB0:
	.text
.LHOTB0:
	.p2align 4,,15
	.globl	_Z6acceptii
	.type	_Z6acceptii, @function
_Z6acceptii:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	movl	%esi, %ebp
	subq	$8, %rsp
	.cfi_def_cfa_offset 32
	call	_Z21queryBudgetAmountByIdi
	movl	%ebp, %edi
	movl	%eax, %ebx
	call	_Z19queryStuffPriceByIdi
	cmpl	%eax, %ebx
	setge	%al
	addq	$8, %rsp
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE0:
	.size	_Z6acceptii, .-_Z6acceptii
	.section	.text.unlikely
.LCOLDE0:
	.text
.LHOTE0:
	.ident	"GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2"
	.section	.note.GNU-stack,"",@progbits

nicest.asm

Salida de

g++ -std=c++11 simplest.cpp -o simplest.asm -O3 -S
	.file	"nicest.cpp"
	.section	.text.unlikely,"ax",@progbits
.LCOLDB0:
	.text
.LHOTB0:
	.p2align 4,,15
	.globl	_Z6acceptii
	.type	_Z6acceptii, @function
_Z6acceptii:
.LFB18:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	pushq	%rbx
	.cfi_def_cfa_offset 24
	.cfi_offset 3, -24
	movl	%esi, %ebp
	subq	$8, %rsp
	.cfi_def_cfa_offset 32
	call	_Z21queryBudgetAmountByIdi
	movl	%ebp, %edi
	movl	%eax, %ebx
	call	_Z19queryStuffPriceByIdi
	cmpl	%ebx, %eax
	setle	%al
	addq	$8, %rsp
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE18:
	.size	_Z6acceptii, .-_Z6acceptii
	.section	.text.unlikely
.LCOLDE0:
	.text
.LHOTE0:
	.ident	"GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2"
	.section	.note.GNU-stack,"",@progbits

Diferencias

Salida de

diff nicest.asm simplest.asm
1c1
< 	.file	"nicest.cpp"
---
> 	.file	"simplest.cpp"
10c10
< .LFB18:
---
> .LFB0:
25,26c25,26
< 	cmpl	%ebx, %eax
< 	setle	%al
---
> 	cmpl	%eax, %ebx
> 	setge	%al
35c35
< .LFE18:
---
> .LFE0:

This is an example to show the power of gcc optimizer. It can generate almost the same Assembly for either a general object oriented abstracted code and the simplest way to do the same thing.

Versión de compilador

g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.9.2-10ubuntu13' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.2 (Ubuntu 4.9.2-10ubuntu13)

simplest.cpp

int f(int a, int b) {
    return a + b;
}

nicest.cpp

template<class T>
class Number {
  public:
    T val;
    Number() {;}
    Number(T v) : val{v} {;}
    T operator+(const Number<T>& i) const { return val + i.val; }
};

int f(int a, int b) {
    auto aa = Number<int>{a};
    auto bb = Number<int>{b};
    return aa + bb;
}

simplest.asm

Salida de

g++ -std=c++11 simplest.cpp -o simplest.asm -O3 -S
	.file	"simplest.cpp"
	.section	.text.unlikely,"ax",@progbits
.LCOLDB0:
	.text
.LHOTB0:
	.p2align 4,,15
	.globl	_Z1fii
	.type	_Z1fii, @function
_Z1fii:
.LFB0:
	.cfi_startproc
	leal	(%rdi,%rsi), %eax
	ret
	.cfi_endproc
.LFE0:
	.size	_Z1fii, .-_Z1fii
	.section	.text.unlikely
.LCOLDE0:
	.text
.LHOTE0:
	.ident	"GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2"
	.section	.note.GNU-stack,"",@progbits

nicest.asm

Salida de

g++ -std=c++11 simplest.cpp -o simplest.asm -O3 -S
	.file	"nicest.cpp"
	.section	.text.unlikely,"ax",@progbits
.LCOLDB0:
	.text
.LHOTB0:
	.p2align 4,,15
	.globl	_Z1fii
	.type	_Z1fii, @function
_Z1fii:
.LFB3:
	.cfi_startproc
	leal	(%rdi,%rsi), %eax
	ret
	.cfi_endproc
.LFE3:
	.size	_Z1fii, .-_Z1fii
	.section	.text.unlikely
.LCOLDE0:
	.text
.LHOTE0:
	.ident	"GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2"
	.section	.note.GNU-stack,"",@progbits

Diferencias

Salida de

diff nicest.asm simplest.asm
1c1
< 	.file	"nicest.cpp"
---
> 	.file	"simplest.cpp"
10c10
< .LFB3:
---
> .LFB0:
15c15
< .LFE3:
---
> .LFE0:
## Backup de página
Este comando crea una versión estática descargable de la página. No funciona cuando la página es demasiado dinámica. (JS o PHP). pensar que este comando lo que hace es recorrer todos los links posibles dentro del dominio. Los que reciban variables URL por get los transforma a una url basada en html (ej : index.php?a=1&b=2 => index.php@a=1&b=2.html). Lo que no hace el script es llenar formularios por lo que todas las redirecciones provenientes de formularios no las procesa. Tampoco lo hace con lo que provenga de javascript pues wget no ejecuta dicho código.
```bash
wget --recursive --page-requisites --adjust-extension --span-hosts --convert-links --domains yoursite.com --no-parent yoursite.com
```
## Redirect no cache HTML
```html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="time; URL=https://gist.github.com/edwrodrig" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
</head>
<body>
</body>
</html>
```
## Bajar carpeta ftp por consola
```bash
wget -r -N -l inf --user="username "--ask-password ftp://path
```

400 : Bad Request

  • Cuando un parametros por post viene en un formato incorrecto:
    • un número que es una palabra
    • null cuando es not null
  • Cuando se hacen operaciones sobre elementos no encontrados.

404 : Not found

  • Cuando un elemento no se encuentra en la base de datos
  • Cuando un elemento se encuentra en la base de datos pero no corresponde al usuario.
    • Se opta por esto porque, si se dice no autorizado entonces se entrega información que el usuario no está autorizado.

QEMU

QEMU Tutorial

SheepShaver

#!/bin/bash
cd "$(dirname "$0")"

./qemu-system-ppc -L pc-bios -boot d -M mac99,via=pmu -m 512 \
-prom-env 'auto-boot?=true' -prom-env 'boot-args=-v' -prom-env 'vga-ndrv?=true' \
-drive file=MacOS9.2.iso,format=raw,media=cdrom \
-drive file=MacOS9.2.img,format=raw,media=disk \
-netdev user,id=network01 -device sungem,netdev=network01 \
-device VGA,edid=on \

Comandos útiles para configurar máquinas

  • named-checkconf : Verificar archivo de configuración de bind
  • named-checkzone : Verificar archivo de zona de bind

IP que hay que agregar a una zona DNS para apuntar a github pages

https://help.github.com/es/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site

  • 185.199.108.153
  • 185.199.109.153
  • 185.199.110.153
  • 185.199.111.153

Configuración de DNS secundario NIC

El servidor 200.1.123.7 es el servidor secundario nic que mecionan en la siguiente configuración. https://www.nic.cl/dominios/secundario/configuracion.html

Información sobre configuración de DNS

Que significa notify

Notifica que una zona se a cargado o cambiado. Se envían a todos lo servidores en los NS records exception a si mismo y al master primario definidio en el SOA record y a cualquier registro que esta en also-notify https://www.zytrax.com/books/dns/ch7/xfer.html#notify

SOA

Significa start of authority record

Que significa allow transfer

https://www.zytrax.com/books/dns/ch7/xfer.html#allow-transfer

Checkeos de configuraciones

Última actualizacion: 2023-09-24

  • haproxy -f config.file -c : Verificar configuración de haproxy
  • nginx -t : Verificar configuración de nginx
  • apachectl configtest : Verificar configuración de apache
  • sudo dmidecode -t 2 : Obtener info de placa madre

Probar que IP especifica responde a dominio

Última actualizacion: 20243-09-24

Obtener la respuesta de una HTTP request con el dominio forzando una IP específica, es decir, sin utilizar el DNS para resolver el nombre. Es útil cuando se quiere descartar que el servidor httpd este mal configurado. Si curl responde correctamente, entonces quiere decir que el problema puede estar a nivel de DNS.

curl http://DOMAIN/some_path --resolve 'DOMAIN:PORT:IP'

Configuracion rápida por numero para nginx

server {
        listen 80;
        listen [::]:80;

        server_name ~^torneo(?<number>\d\d)\.dev\.labo86\.cl;
        client_max_body_size 100M;

        location / {
                   proxy_pass http://127.0.0.1:8804/t$number/var/www$request_uri;
        }

}

Habilita un puerto tcp de entrada por el firewall de ubuntu

ufw allow in PORT/tcp comment 'ALGUNA DESCRIPCION'

Ver puertos abiertos en linux

sudo lsof -i -P -n | grep LISTEN netstat -tulpn

Probar puertos de salida

Usar este servidor público http://portquiz.net/ Lo más básico es usar el comando telnet portquiz.net 80

Configuración básica ufw

  • sudo ufw default deny incoming
  • sudo ufw default allow outgoing

Listar hardware de red

sudo lshw -C network

Listar dispositivos pci ethernet

lspci | grep -i ethernet

Ver mensajes de diagnóstico de drivers del kernel

cat dmesg | grep -i eth

Agregar o sacar modulos del kernel

modprobe

CERBOT

EMAIL=some@mail DOMAIN=some_domain dudo certbot certonly --manual --preferred-challenges dns --email $EMAIL --agree-tos -d $DOMAIN

Juntar llaves para certificado de haproxy

DOMAIN='example.com' sudo -E bash -c 'cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/letsencrypt/live/$DOMAIN/privkey.pem > /etc/haproxy/certs/$DOMAIN.pem'`

Links

https://dev.to/michaeldscherr/lets-encrypt-ssl-certificate-via-dns-challenge-8dd https://certbot.eff.org/docs/using.html#manual https://www.digitalocean.com/community/tutorials/how-to-secure-haproxy-with-let-s-encrypt-on-ubuntu-14-04

Código

Sirve para poder acceder a elementos de un arreglo multidimensional sin preocuparse de la estructura. De una forma simplicada, es lo mismo array['a']['b']['c] == array['c']['a']['b].

<?php
declare(strict_types=1);

class SmartArray {

public $data = [];

public function __construct(array $data = []) {
  $this->data = $data;
}

private static function search_in_array(array $data, $keys) {
  foreach ( $keys as $index => $key ) {
    if (isset($data[$key]))
      return $index;
  }
  return null;
}

public function __invoke(...$keys) {
  $data = $this->data;

  while ( !empty($keys) ) {
    $index = self::search_in_array($data, $keys);
    if ( is_null($index) ) return null;
    $data = $data[$keys[$index]];
    array_splice($keys, $index, 1);
  }

  return $data;
}

}

Uso

$data = [
 'a1' => [
   'b1' => 1,
   'b2' => 2
 ],
 'a2' => [
   'b1'=> 3,
   'b2' => [
     'c1' => 2
   ]
 ]
];

$data = new SmartArray($data);

var_dump($data('a1', 'b1'));
var_dump($data('b1', 'a1'));


var_dump($data('a2', 'b1'));
var_dump($data('b1', 'a2'));

var_dump($data('a2', 'b2', 'c1'));
var_dump($data('c1', 'b2', 'a2'));
var_dump($data('b2', 'c1', 'a2'));

Como obtener la linea de una llamada de una función

Código

function hola() {
  var_dump(debug_backtrace()[0]);
}

function chao() {
  hola();
}

chao();

Salida

array(4) {
  ["file"]=>
  string(20) "/home/USER/hola.php"
  ["line"]=>
  int(8)
  ["function"]=>
  string(4) "hola"
  ["args"]=>
  array(0) {
  }
}

Current working dir del script

Último cambio: 2023-09-24 Obtiene la ruta absoluta del directorio en que se encuentra el script. Esto es similar ala variable __DIR__ de php.

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

Notar que no incluye el backslash al final de la ruta.

Un ejemplo de uso: cp -rf ${SCRIPT_DIR}/.. /some/path

Guardar contenido de un archivo en una variable

Último cambio: 2024-01-28

VARIABLE=$(cat some/path/to/file)

Una mejor forma pero más verbosa

IFS='' read -r -d '' VARIABLE <<-'EOF'
    abc'asdf"
    $(dont-execute-this)
    foo"bar"''
EOF

Para cargar en modo bootloader

adb reboot bootloader

Para cambiar configuración con fastboot

Cambia la configuración para deshabilitar que se mantenga apagado en carga, o refraseando, habilitar que se prenda automaticamente cuando hay carga. Fastboot debe estár instalado. Generamente se encuentra en /home/USER/Android/Sdk/platform-tools/fastboot

./fastboot oem off-mode-charge 0

1.- Instalar el programa Ghostscript. Para ello, abre terminal y escribe:

sudo apt-get install ghostscript

2.- Una vez instalado el programa, dirígite a la carpeta donde está el archivo:

cd /home/usuario/nombredelarchivo

3.- Ejecuta el siguiente comando en el terminal para reducir el tamaño:

gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=pdf_reducido.pdf pdf_original.pdf

A continuación podéis ver las opciones de -dPDFSettings:

dPDFSETTINGS=/screen (72 dpi, menor tamaño y peor calidad)
dPDFSETTINGS=/ebook (150 dpi, calidad media)
dPDFSETTINGS=/printer (300 dpi, alta calidad)
dPDFSETTINGS=/prepress (300 dpi, alta calidad preservando el color)
dPDFSETTINGS=/default (casi idéntico a screen, pero con calidad ligeramente superior)

Para entrar a mysql como root en Ubuntu

Última fecha: 2023-09-24

sudo mysql --defaults-file=/etc/mysql/debian.cnf

Crear una base de datos

Última fecha: 2023-09-24

CREATE DATABASE DB_NAME;
CREATE USER 'DB_USER'@'localhost' IDENTIFIED WITH mysql_native_password BY 'DB_PASSWORD';
GRANT ALL PRIVILEGES ON DB_NAME.* TO 'DB_USER'@'localhost';

Reemplazar DB_NAME, DB_USER y DB_PASSWORD según corresponda.

Configuración de native password en ubuntu 20.04 LTS

Última fecha: 2023-09-24

Entrar en el archivo /etc/mysql/mysql.conf.d/mysqld.cnf y agregar o modificar el siguiente parámetro.

default-authentication-plugin=mysql_native_password

Referencias:

Comando SQL útiles para debugear

SHOW PLUGINS;
select User, plugin from mysql.user;
show grants for 'user'@'localhost';
show variables LIKE 'default%'

Script para rotar un monitor en 180 grados en raspbian 2024-01-31 poner en ~/.config/autostart

<?php
mb_internal_encoding("UTF-8");

function getIdByName($text, $name) {
    $lines = explode("\n", $text);

    foreach ($lines as $line) {
        if (mb_strpos($line, $name) !== false) {
            preg_match('/id=(\d+)/', $line, $matches);
            if (isset($matches[1])) {
                return $matches[1];
            }
        }
    }

    return null;
}

function getIdOfFirstMonitor($text) {
    $lines = explode("\n", $text);

    foreach ($lines as $line) {
	echo $line;
        if (mb_strpos($line, "HDMI") === false) continue;
	
        $columnas = explode(' ', trim($line));
        $ultimaColumna = end($columnas);
        return $ultimaColumna;

    }

    return null;
}

$xrandrOutput = shell_exec('xrandr --listmonitors');
$inputOutput = shell_exec('xinput');

$searchName = "WaveShare WS170120";
$id = getIdByName($inputOutput, $searchName);

if ($id !== null) {
    echo "The ID of '$searchName' in xrandr is: $id\n";
} else {
    echo "'$searchName' not found in the xrandr output.\n";
}

$idOfFirstMonitor = getIdOfFirstMonitor($xrandrOutput);

if ($idOfFirstMonitor !== null) {
    echo "The ID of the first monitor in input is: $idOfFirstMonitor\n";
} else {
    echo "No information about the first monitor found in the input output.\n";
}

$cmd = "xrandr --output $idOfFirstMonitor --rotate inverted";

echo $cmd;

passthru($cmd);


$cmd = "xinput map-to-output $id $idOfFirstMonitor";

echo $cmd;

passthru($cmd);

Para cambiar el splash image en raspbian bookworm,se necesita actualizar el kernel

https://forums.raspberrypi.com/viewtopic.php?t=357885

Para cambiar la imagen del menu

Cambiar matchbox keyboard

https://stackoverflow.com/questions/70574505/how-to-change-the-default-matchbox-keyboard-layout

https://forums.raspberrypi.com/viewtopic.php?t=275473

I've managed to change the Menu icon doing the following steps:

  1. Right click Menu Icon in Task Bar, and click on "Menu Settings".
  2. Change Icon name from "start-here" to "rpi".
  3. Store new icon image in Pictures folder or any other folder.
  4. Replace the rpi.png in the following paths:

$ sudo cp ~/Pictures/newIcon.png /usr/share/icons/hicolor/32x32/apps/rpi.png $ sudo cp ~/Pictures/newIcon.png /usr/share/icons/PiXflat/16x16/apps/rpi.png $ sudo cp ~/Pictures/newIcon.png /usr/share/icons/PiXflat/24x24/apps/rpi.png $ sudo cp ~/Pictures/newIcon.png /usr/share/icons/PiXflat/32x32/apps/rpi.png $ sudo cp ~/Pictures/newIcon.png /usr/share/icons/PiXflat/48x48/apps/rpi.png

Hope it helps. :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment