Mensuel Shaarli
November, 2017
En résumé :
La 151 correspond à une CPU (Critical Patch Update) cependant certains bugs pas critiques passent à travers les mailles du filet ; à cet instant Oracle fourni des quicks fixes mais développé en mode "dirty quick fixes" et cela donne la 152 ce qui correspond à une PSU (Patch Set Update).
Les correctifs de la 152 seront intégrés à la prochaine 155 donc si vous n'êtes pas impactés par les bugs corrigés par la 152, toujours utilisez la 151 (les versions impaires si vous préférez).
Procédons par étape :
- Formatter vos carte SD en FAT32 (1 seule partition prenant tout l'espace disponible).
- Télécharger l'image de la dernière Rapbian disponible ici.
- Identifier sur quel lecture votre carte SD se trouve en utilisant la commande fdisk :
sudo fdisk -lN.B : chez moi il s'agit de /dev/sdb1
- Aller dans le répertoire où vos avez téléchargé votre Raspbian (à l'heure où j'écris il s'agit de la 2017-09-07) :
- Saisissez la commande (en remplaçant mes valeurs par les votres, ne soyez pas stupide hein) :
# Explications : # 'dd' permet de faire une copie bit à bite de l'image vers votre carte SD. # 'if' signifie "Input File", c'est la source des données à transférer # 'of' signifie "Ouput File", c'est la destination des données lors du transfert # conf=fsync est une option de contrôle utilisée par 'dd' lors de la copie # status=progress permet d'afficher la progression de la copie sudo dd bs=4M if=2017-09-07-raspbian-stretch-lite.img of=/dev/sbd status=progress conv=fsync - Une fois l'opération terminée, démontez correctement votre clef USB et branchez-là sur votre Raspberry Pi
Remarques :
- Sur certaines cartes SD, l'option bs=4M doit être descendue à bs=1M autrement l'écriture ne se fera pas.
- Sur certaines version de la commande 'dd', l'option status=process soit n'affiche rien, soit empêche l'écriture ; auquel cas il faut la retirer.
Ce qui donne :
sudo dd bs=1M if=2017-09-07-raspbian-stretch-lite.img of=/dev/sbd conv=fsyncCréer une boite modal pour un petit site.
Introduction
Comme vous le savez sûrement, il existe une légende sur internet congrue à l'arrivée de Maven 3 : il est possible d'écrire des pom en Yaml. Eh bien sachez que la chose n'est en rien une légende.
En effet, les versions Maven 3.x et supérieures recherchent - avant de lire le pom.xml - un fichier spécifique dans ./mvn/extensions.xml. Ce fichier va charger des extensions à Maven lui permettant de faire plus de choses.
L'idée est donc de demander à Maven de charger l'extension polyglot-yaml qui va ajouter à Maven la capacité d'interpréter du Yaml.
Mise en oeuvre
- À la racine de votre projet créez le répertoire ./mvn/
- Créez dans ce répertoire le fichier extensions.xml dont le contenu est le suivant :
<?xml version="1.0" encoding="UTF-8"?> <extensions> <extension> <groupId>io.takari.polyglot</groupId> <artifactId>polyglot-yaml</artifactId> <version>0.2.1</version> </extension> </extensions> - Créez un fichier pom.yml à la racine de votre projet
- A titre d'exemple, voici un modèle de pom parent en Yaml :
modelEncoding: 'UTF-8'
modelVersion: '4.0.0'
groupId: 'com.enterprise.fivestars.fs'
artifactId: 'fs-project'
version: '1.0.0-SNAPSHOT'
packaging: 'pom'
name: '. ${project.artifactId} [${project.version}]'
properties:
## Project encoding
project.encoding: 'UTF-8'
project.build.sourceEncoding: '${project.encoding}'
project.reporting.outputEncoding: '${project.encoding}'
## Maven compiler
maven.compiler.source: '1.8'
maven.compiler.target: '${maven.compiler.source}'
## Kotlin compiler
kotlin.compiler.jvmTarget: '${maven.compiler.source}'
kotlin.source.directory: '${project.basedir}/src/main/kt'
kotlin.test.directory: '${project.basedir}/src/test/kt'
kotlin.version: '1.1.51'
## Loggers
logback.version: '1.1.7'
slf4j.version: '1.7.22'
modules:
- fs-domain
- fs-main
- fs-persistence
dependencyManagement:
dependencies:
## Project dependencies
- { groupId: '${project.groupId}' , artifactId: 'fs-project' , version: '${project.version}' }
- { groupId: '${project.groupId}' , artifactId: 'fs-domain' , version: '${project.version}' }
- { groupId: '${project.groupId}' , artifactId: 'fs-persistence' , version: '${project.version}' }
## Database - Driver & embedded DB
- { groupId: 'com.h2database' , artifactId: 'h2' , version: '1.4.195' }
## Database - Database migration
- { groupId: 'org.flywaydb' , artifactId: 'flyway-core' , version: '4.2.0' }
## Database - Connection Pool
- { groupId: 'com.zaxxer' , artifactId: 'HikariCP' , version: '2.7.2' }
## Database - Persistence framework
- { groupId: 'org.javalite' , artifactId: 'activejdbc' , version: '1.4.13.j7' }
## Dependencies Injection
- { groupId: 'org.codejargon.feather' , artifactId: 'feather' , version: '1.0' }
## Kotlin - JVM & Collection compliance
- { groupId: 'org.jetbrains.kotlin' , artifactId: 'kotlin-stdlib' , version: '${kotlin.version}' }
- { groupId: 'org.jetbrains.kotlin' , artifactId: 'kotlin-stdlib-jre8' , version: '${kotlin.version}' }
## Logger - Logging framework facad
- { groupId: 'org.slf4j' , artifactId: 'slf4j-api' , version: '${slf4j.version}' }
## Logger - Logging framework
- { groupId: 'ch.qos.logback' , artifactId: 'logback-classic' , version: '${logback.version}' }
## Testing dependencies
- { groupId: 'org.assertj' , artifactId: 'assertj-core' , version: '3.8.0' }
- { groupId: 'org.jetbrains.kotlin' , artifactId: 'kotlin-test' , version: '${kotlin.version}' }
- { groupId: 'org.junit.platform' , artifactId: 'junit-platform-runner' , version: '1.0.1' }
- { groupId: 'org.mockito' , artifactId: 'mockito-core' , version: '2.12.0' }
build:
pluginManagement:
plugins:
## Compiler - Java (Prevent its execution because of Kotlin)
- artifactId: 'maven-compiler-plugin'
groupId: 'org.apache.maven.plugins'
version: '3.6.2'
configuration:
compilerArgs: {arg: '-Werror'}
encoding: '${project.build.sourceEncoding}'
fork: true
debug: false
optimize: true
showDeprecation: true
showWarnings: true
source: '${maven.compiler.source}'
target: '${maven.compiler.target}'
executions:
- goals:
id: 'default-compile'
phase: 'none'
- goals:
id: 'default-testCompile'
phase: 'none'
- goals: ['compile']
id: 'java-compile'
phase: 'compile'
- goals: ['testCompile']
id: 'java-test-compile'
phase: 'compile'
## Compiler - Kotlin
- artifactId: 'kotlin-maven-plugin'
groupId: 'org.jetbrains.kotlin'
version: '${kotlin.version}'
configuration:
nowarn: false
jvmTarget: '${kotlin.compiler.jvmTarget}'
executions:
- goals: ['compile']
id: 'compile'
phase: 'compile'
configuration:
sourceDirs: [
'${kotlin.source.directory}'
]
- goals: ['test-compile']
id: 'test-compile'
phase: 'test-compile'
configuration:
sourceDirs: [
'${kotlin.test.directory}'
]
## ActiveJDBC - Enrich entities bytecode
- artifactId: 'activejdbc-instrumentation'
groupId: 'org.javalite'
version: '1.4.13.j7'
executions:
- goals: ['instrument']
id: 'enrich-entities'
phase: 'process-classes'
## Quality - JaCoCo (Code coverage)
- artifactId: 'jacoco-maven-plugin'
groupId: 'org.jacoco'
version: '0.7.9'
executions:
- goals:
id: 'prepare-agent'
inherited: true
- goals:
id: 'report'
inherited: true
phase: 'prepare-package'
Et la même chose avec un pom enfant :
modelEncoding: 'UTF-8'
modelVersion: '4.0.0'
parent:
groupId: 'com.enterprise.fivestars.fs'
artifactId: 'fs-project'
version: '1.0.0-SNAPSHOT'
relativePath: '../pom.yml'
artifactId: 'fs-persistence'
packaging: 'jar'
name: '${project.artifactId}'
dependencies:
## Kotlin - JVM & Collection compliance
- { groupId: 'org.jetbrains.kotlin' , artifactId: 'kotlin-stdlib' , scope: 'compile' }
- { groupId: 'org.jetbrains.kotlin' , artifactId: 'kotlin-stdlib-jre8' , scope: 'compile' }
## Database - Database migration
- { groupId: 'org.flywaydb' , artifactId: 'flyway-core' , scope: 'compile' }
## Database - Driver & embedded DB
- { groupId: 'com.h2database' , artifactId: 'h2' , scope: 'compile' }
## Database - Connection Pool
- { groupId: 'com.zaxxer' , artifactId: 'HikariCP' , scope: 'compile' }
## Logger - Logging framework facade
- { groupId: 'org.slf4j' , artifactId: 'slf4j-api' , scope: 'compile' }
## Logger - Logging framework
- { groupId: 'ch.qos.logback' , artifactId: 'logback-classic' , scope: 'compile' }
## Testing dependencies
- { groupId: 'org.assertj' , artifactId: 'assertj-core' , scope: 'test' }
- { groupId: 'org.jetbrains.kotlin' , artifactId: 'kotlin-test' , scope: 'test' }
- { groupId: 'org.junit.platform' , artifactId: 'junit-platform-runner' , scope: 'test' }
- { groupId: 'org.mockito' , artifactId: 'mockito-core' , scope: 'test' }
build:
plugins:
- { groupId: 'org.jetbrains.kotlin' , artifactId: 'kotlin-maven-plugin' }
- { groupId: 'org.apache.maven.plugins' , artifactId: 'maven-compiler-plugin' }
- { groupId: 'org.jacoco' , artifactId: 'jacoco-maven-plugin' }
Et en prime, vous savez à présent compiler du Kotlin avec Maven.
Une superbe explication par Franck Lepage. Merci Animal d'avoir extrait de facebook ce poste limpide par son écriture et effroyable par son constat.
Pour toi Animal :p
via : Sebsauvage
Rappel des définitions
PWA : Progressive Web App.
SPA : Single Page Application (voir ce post).
Introduction
Une PWA est fondamentalement une SPA à laquelle a été ajouté deux choses :
- Elle se comporte comme une application native sur les appareils (Mobile, Tablette et PC).
En d'autres termes, l'utilisateur trouvera sur son bureau une icône du site web développé à partir de la technologie PWA.
Elle peut travailler en mode déconnecté via ce que l'on appelle les Service Workers.
Fondamentalement qu'est-ce que ça change ?
Côté mobile, l’utilisateur installe la PWA de deux façons :
- Soit via un simple bookmark posé sur son bureau.
- Soit via un AppStore qui lui créera une icône sur son bureau.
Il a dont l'impression "d'installer une appli" et non plus de "surfer sur internet".
Si une panne de réseau survient, les Service Workers de la PWA vont prendre le relais et :
- Soit empiler les requêtes en fournissant les données précédentes.
- Soit en calculant les données requises (si possible).
Le Service Worker agit donc un peu comme un proxy, mais côté client, à qui le navigateur délègue l'accès au réseau.
Le gros avantage de la PWA sur les applications natives est qu'il n'est plus nécessaire de développé une version de GUI par plateforme mais tout via des technos web (Aurelia, Angular, Vue, etc).
Il suffit d'ajouter le paramètre -Dmaven.repo.local à la ligne de commande :
mvn -Dmaven.repo.local=/path/to/repositoryRendre son site web accessible. Bon article
Un tuto en français montrant comment configurer un couche SSL sur nginx.
Comment ajouter l'autocompletion dans le shell
1) Installer le paquet :
apt-get install bash-completion
2) Ajouter à votre ~/.bashrc :
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
Et voilà !
Explication du problème :
La plupart du temps, les VM sont synchronisées avec l'horloge de l'hyperviseur directement et non un serveur de temps. Ce dernier étant lui-même synchronisé avec un serveur NTP (ndr. le serveur de temps).
Le fait est que la synchronisation des threads en Java s'appuie sur des mécanismes de pool de threads et de mise en pause pendant certaines durées ; durées définies par la JVM elle-même et le garbage collector. Or, l'hyperviseur peut - pour des raisons de performances et en cas de partage des ressources physiques entre plusieurs VM - désynchroniser l'horloge des VM avec le "vrai" temps.
Par exemple, il peut y avoir une pause de l'horloge qui dure 40 secondes et l'hyperviseur choisira alors de synchroniser un grand coup les horloges de toutes les VM en cours d'exécution.
Et alors, quel est le problème avec Java ?
Tout simplement qu'à cet instant, tous les threads qui auraient du n'être en pause que quelques millisecondes vont s'activer un grand coup simultanément ce qui va fortement augmenter la charge du CPU et dégrader énormément les performances (puisqu'il n'y a plus partage des ressources via une attribution séquentielle mais concurrence pour accéder à la même ressource : le CPU).
Bref, c'est du caca. En résumé,
Fabriquer des charts jolis en JS pure sans dépendance et qui tiennent la charge.
Présentation rapide de LXC, une technologie qui gagnerait à être connue
Donc j'ai ris.
Quand allons-nous abandonner cette hérésie écologique qu'est la blockchain ? Le bitcoin est une monnaie inégalitaire, déflationniste, énergivore, spéculative et morcelée (c'est-à-dire qu'il existe plusieurs bitcoins parce que pourquoi pas).
Vous souhaitez une monnaie qui vous respecte ? Alors jetez à la poubelle les monnaies qui favorisent les hypra-riches et tournez-vous vers des solutions libres, interopérables, équitables, justes, fiables et démocratiques, en premier lieu : http://trm.creationmonetaire.info/
Toujours utile, je compléterai ce poste avec mes "astuces" plus tard.
L'auteur d'origine déclare un gain de 45 min, alors pourquoi ne pas essayer.
Les documents "confidentiels" de l'état français mais qui sont indexés sur Google quand même parce que les admin sys de l'état font très mal leur travail.
Le morceau de code JS de la page :
La partie HTML :
<body onscroll="OnScrollDiv()" onload="OnScrollDiv()">
<div class="lazy"></div><div class="lazy"></div><div class="lazy"></div><div class="lazy"></div><div class="lazy"></div><div class="lazy"></div>
... (la ligne du dessus est répétée n-fois
<script>...</script>
</body>
La partie JS :
function OnScrollDiv() {
var elems = document.getElementsByClassName('lazy');
var el = elems[0];
for (var i = 0, nb=elems.length ; i < nb ; i++, el = elems[i]) {
var rect = el.getBoundingClientRect();
// $isVisible contains "true" or "false" weither the element is visible or not
var isVisible = ((rect.top - window.innerHeight) < (0 - 200) && (200 < rect.bottom));
if (isVisible) {
el.classList.add('blue-block');
}
else {
el.classList.remove('blue-block');
}
}
}L'idée est de comprendre les bases du mode reverse proxy de nginx. Pour moi, c'est le mécanisme d'url rewriting qui est le plus intéressant sachant sur les liens dans les pages doivent eux-aussi êtres réécrits.
Animal, merci pour le documentaire. Je le regarderai courant décembre, pas le temps cette semaine.
Animal, tu dis du caca... Il n'y a pas AIR dedans. Je doute même que ce soit toi qui aies posté cette liste !
Le setup est vraiment facile :
1) Créer le fichier /etc/network/interfaces.d/wifi
2) Ajouter le contenu suivant (en l'adaptant)
auto lo
iface lo inet loopback
iface eth0 inet dhcp
allow-hotplug wlan0
auto wlan0
iface wlan0 inet dhcp
wpa-ssid "nom du réseau"
wpa-psk "mot de passe wifi"
3) Redémarrer votre Raspberry
Différence entre WebApp & SPA
Pour bien comprendre la différence, analysons le schéma placé en lien.
La partie supérieure montre bien qu'à chaque requête, toute la page est rechargée. C'est-à-dire que le navigateur va télécharger du HTML + du contenu (en supposant qu'il dispose déjà dans son cache de tous les CSS et JS dont il a besoin).
En-dessous se trouve la SPA, celle-ci va télécharger tout le HTML et le JS lors de la première requête uniquement. Ensuite, seule des données sont échangées entre le client et le serveur, généralement au format JSON (je précise minifié, ceci afin d'obtenir les meilleures performances possibles).
Quand utiliser quoi ?
- Lorsque vos utilisateurs surfent très peu sur votre site et qu'ils ont besoin d'accéder à du contenu rapidement, alors la WebApp est la solution à privilégier - le coût de chargement de la page étant réduit à l'ensemble des informations servant l'utilisateur).
- À l'inverse si vos utilisateurs sont connectés pendant dès heures sur votre site et qu'ils passent sans arrêt de page en page, alors la SPA est à privilégier - tout simplement parce que le coût de téléchargement de la première page (qui contient en réalité toutes les pages du site) est alors rentabilisé par le surf de longue durée.
Quelles technos pour des SPA ?
Les plus connues sont rangées par ordre décroissant d'importance sur le marché :
- Angular
- Vue JS
- React JS (+ redux)
- Ember JS
- Aurelia (qui est de loin ma préférée)
Un super menu en JS. Le second effet et top-moumoutte !
Dans tous les cas de figures, modifier le fichier /etc/nginx/nginx.conf.
# Cacher la version de nginx dans les pages d'erreur :
# Décommentez cette section
server_tokens off;Quand comprendras-tu ? Plus tu prends, et moins tu possèdes...
Maître Oogway
Tout est dit !
Lenny, nous parlions des FlexBox et des CSS Grid qui les complètent. Voici une page qui résume parfaitement les FlexBox.
Walk off the earth toujours excellent !
Et la reprise de Shake it Of de Taylor Swift ici
Introduction Les métriques sont la partie la plus visible d'une architecture de supervision. Ce sont des données en général facile à récupérer et à stocker. Par conséquent, il arrive souvent qu'on n'investisse pas assez de temps dans la compréhension des données collectées, du pourquoi nous les collectons et ce que …
Un micro server mail !
Analyser les problèmes de votre site web. Pour une fois que Microsoft fait quelque chose d'intelligent (ok j'exagère). Après, je n'ai pas lu leur licence d'utilisation, donc je ne sais pas ce qu'ils font des données glanées.
Un tuto FlexBox / CSS Grid expliquant dans quels cas l'un où l'autre devient intéressant. On y voit clairement la différence entre un positionnement à une dimension (flexbox) et à deux dimensions (grid).
Comme le dit Sebsauvage : RMS avait TELLEMENT raison.
Un humain de sexe masculin peut fort bien être une recrue, une vedette, une canaille, une fripouille ou une andouille. De sexe féminin, il lui arrive d'être un mannequin, un tyran ou un génie. Le respect de la personne humaine est-il réservé aux femmes, et celui des droits de l'homme aux hommes ? Absurde ! Ces féminins et masculins sont purement grammaticaux, nullement sexuels.
J'abonde : la remarque est pertinente.
L'écriture inclusive et tous ces effets cosmétiques autour du langage font croire que les choses changent ; pourtant la stratégie est simple, modifions la surface d'un problème mais surtout laissons-le intact en profondeur, les faibles auront l'illusion d'avoir remporté bataille tandis que les forts préserverons leurs privilèges.
Le racisme a-t-il disparu depuis que les mots nègres, bougnoules, youpin, niakwé & co ont disparu du langage (j'entends par là, des journaux, de la télévision, des radios, des magazines, des affiches, de la publicité, des jouets, etc) ? Non, certains partis politiques (dois-je préciser français) fondent même leur programme dessus ! Mais sur quoi me direz-vous ? Sur l'idée, ce concept, cette croyance exprimant que la couleur de peau, l'origine, l'orientation sexuelle, la maladie ou encore la religion déterminent la valeur des hommes et leur importance dans la société ; en ce sens qu'ils ont eu la bonne idée d'être bien nés.
Le véritable combat ne serait-il pas l'explication et la diffusion d'autres valeurs "morales" ? Le véritable combat ne serait-il pas d'admettre que nous vivons dans un système de prédation totale et que celui-ci écrase, méprise, domine et achève quiconque s'opposerait à lui ; ceci par tous les moyens possibles, en permanence, pour que d'autres - l'extrême petit nombre - préserve l'ensemble de ses avantages ?
Notre société civile ne facilite pas l'oppression, elle est l'oppression ; le langage n'est pas l'oppresseur, les individus qui oppressent sont les oppresseurs. Un couteau ne tue pas, c'est l'homme qui tue en se servant d'un couteau, le langage n'exclut pas, ce sont les individus qui excluent en se servant du langage. Voyez-vous la différence ?
Prôner l'égalité black/blanc/beurre sur des termes moraux est la chose la plus clivante qui soit ; et ne pas se soucier des injustices en termes de richesse, de partage, de solidarité et de respect, je trouve cela abscons et stupide car elles sont à l'origine du premier problème.
Ne me faites pas dire ce que je n'ai pas dit, je sais que les LGBTx souffrent mais il faut s'atteler à corriger la cause des causes et non le reste. Pour info (et ce sujet étant tellement brûlant) je me dois de préciser que je n'ai pas écrit LGBTx pour me moquer des "x", il faut savoir qu'il existe les LGBTI, LGBTA, LGBTQ ou encore LGBTP. Nous devrions donc écrire quelque chose comme LGBTAIQPT afin "d'inclure" vraiment tout le monde parce que l'idée est là, il faudrait en permanence inclure chacun individu dans sa différence à chaque instant de chaque discours... Seriously...
En fait, l'écriture inclusive me fait penser au langage Scala. L'idée semblait bonne au début : incorporons tous les paradigmes dans le même langage afin que chacun puisse l'utiliser à sa guise. Puis, faisons de chacun des cas particuliers, de chacune des exceptions de chaque paradigmes, une règle générale à appliquer systématiquement, tout le temps et pour tout le monde quelque soit le contexte.
Que se passe-t-il ? Cela revient à penser à protéger son code de problèmes comme la variance, co-variance et contra-variance qui ne posent réellement problème que lorsque le code amoncelle une quantité faramineuse de très mauvaises pratiques. Bref, le cas hyper particulier à gérer exceptionnellement devient chose commune.
Et que se passe-t-il à la fin ? À l'intérieur de Scala il y a les scalaïstes objets, les scalaïstes fonctionnels, les scalaïstes évènementiels, les scalaïstes procéduraux, etc. Et plutôt que de rassembler, la communauté a morcelé Scala pour refléter sa propre nature : les uns ne sont pas les autres.
La solution réside dans l'apprentissage de l'acceptation de l'autre, par dans l'interdiction de s'exprimer avec des mots et au travers de la grammaire.