bash – Sam & Max http://sametmax.com Du code, du cul Wed, 23 Dec 2020 13:35:02 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.7 32490438 Nouvel alias pour Python et .bashrc http://sametmax.com/nouvel-alias-pour-python-et-bashrc/ http://sametmax.com/nouvel-alias-pour-python-et-bashrc/#comments Thu, 17 Mar 2016 15:27:41 +0000 http://sametmax.com/?p=18674 J’en avais marre de taper Python en entier. Et surtout, je voulais lancer Python3.5 si il est dispo, et si possible ptpython, ou ipython. Sauf si je passe des arguments. Et que ça pete pas tout dans un virtualenv.

Bref:

function p {
    local SUFFIX="$@"
    if [[ "$VIRTUAL_ENV" != "" ]]
    then
      local PREFIX="$VIRTUAL_ENV"/bin
      COMMANDS=("python")
    else
      local PREFIX=/usr/bin
      COMMANDS=("python3.5" "python")
    fi

    if [[ "$#" -eq 0 ]]; then
        SUFFIX=""
        local COMMANDS=("python3.5 -m ptpython"
                        "python3.5 -m ipython"
                        "python -m ptpython"
                        "python -m ipython"
                        "python")
    fi

    for i in "${COMMANDS[@]}"
    do
       $PREFIX'/'$i $SUFFIX;
       [ "$?" -eq 0 ] && return 0
    done

}
]]>
http://sametmax.com/nouvel-alias-pour-python-et-bashrc/feed/ 7 18674
Mon prompt bash est tout cassé ! http://sametmax.com/mon-prompt-bash-est-tout-casse/ http://sametmax.com/mon-prompt-bash-est-tout-casse/#comments Thu, 14 Jan 2016 09:43:33 +0000 http://sametmax.com/?p=17806 Ça m’était déjà arrivé plusieurs fois après avoir ajouté mon env virtuel et ma branch git dans mon prompt : soudainement il se met à faire n’importe quoi. Des mixes de caractères, des sauts de ligne qui se font pas, la fusion de la ligne de commande sur elle-même.

Inutilisable.

Aujourd’hui plutôt que de subir le problème, j’ai cherché une solution, et pouf : quand on utilise des couleurs dans son prompt, il faut entourer tout le balisage de [].

Mais le balisage qui colore le prompt est composé de séquences d’échappements, qui contiennent aussi [], donc il faut mettre des anti-slash.

Du coup on passe de ça :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')\e[0m $PS1"

à :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')[\e[0m] $PS1"

à la solution qui marche :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')\[\e[0m\] $PS1"

Évidemment à appliquer à tous les codes d’échappement chelou qu’on a réparti un peu partout.

J’ai un tampon prêt à tirer pour le premier qui me parle de zsh.

]]>
http://sametmax.com/mon-prompt-bash-est-tout-casse/feed/ 24 17806
On a tenté de nous hacker 0bin http://sametmax.com/on-a-tente-de-nous-hacker-0bin/ http://sametmax.com/on-a-tente-de-nous-hacker-0bin/#comments Sun, 20 Dec 2015 09:36:38 +0000 http://sametmax.com/?p=17160 En me baladant dans l’arbo de 0bin.net pour retirer un dox qu’on m’avait signalé je suis tombé sur un dossier au nom bizarre :

# ls -l
total 4
4 drwxr-xr-x 7 root root 4096 sept. 24  2014 --

Hum, voilà qui n’est pas pratique à analyser depuis le bash. Et pourquoi j’ai ce dossier-là d’ailleurs ?

Regardons ce qu’il y a dedans :

# python -c "import os; os.rename('--', "strange_dir")"
# ls strange_dir/
3Q  Dk  k5  Oh  -u

Oh, y a un dossier nommé “-u”…

A ce stade-là, j’ai juste supprimé le truc.

Et j’ai réalisé : on crée les dossiers de l’arbo en fonction du nom du paste, qui est une clé générée côté client, et donc fournie par un code JavaScript non trusté.

Du coup l’attaqueur nous a sans doute passé une commande bash comme nom de fichier. J’imagine, espérant qu’on fabriquait le fichier avec une exécution shell. Comme on utilise le module os pour le faire, je pense que ça n’a eu aucun impact.

J’espère :)

]]>
http://sametmax.com/on-a-tente-de-nous-hacker-0bin/feed/ 8 17160
Rejouer un session de terminal avec playitagainsam http://sametmax.com/rejouer-un-session-de-terminal-avec-playitagainsam/ http://sametmax.com/rejouer-un-session-de-terminal-avec-playitagainsam/#comments Thu, 22 May 2014 08:29:36 +0000 http://sametmax.com/?p=10298 playitagainsam, ou PIAS a pour but de rejouer des sessions shell: il lance un shell, enregistre ce qu'on y a tapé, et quand on quitte le shell, sauvegarde le tout dans un fichier. Ensuite, on peut lire le contenu du fichier et revoir la session shell telle qu'elle a été tapée.]]> Combien de fois, durant une formation, on m’a demandé si je pouvais donner un dump de la session shell.

playitagainsam, ou PIAS, a exactement pour but de faire cela: il lance un shell, enregistre ce qu’on y a tapé, et quand on quitte le shell, sauvegarde le tout dans un fichier. Ensuite, on peut lire le contenu du fichier et revoir la session shell telle qu’elle a été tapée.

C’est un programme Python, on peut donc le pip installer :

pip install playitagainsam --user

Ensuite, on lance une session à enregistrer avec la sous commande record :

pias record nom_du_fichier_ou_sauver_l_enregistrement 

PIAS va lancer un nouveau shell, par défaut le même que votre shell actuel (souvent bash, pour moi fish), mais vous pouvez préciser un type de shell spécial avec --shell. Ex :

pias record ex1 --shell ipython

A partir de là il n’y a rien à faire. On peut travailler normalement et oublier qu’on a utilisé PIAS. Une fois qu’on a terminé sa petite affaire, il suffit de sortir du shell (CTRL + D, exit, etc), et la session va être sauvegardée dans un format JSON facile à corriger à la main si vous souhaitez la rendre plus agréable :

{
  "events": [
    {
      "act": "OPEN",
      "size": [
        162,
        33
      ],
      "term": "1c53f048e3a74984b2a93af175e24e87"
    },
    {
      "act": "PAUSE",
      "duration": 0.10042214393615723
    },
    {
      "act": "WRITE",
      "data": "\u001b]0;sam@sametmax.com: /tmp\u0007sam@sametmax.com:/tmp$ ",
      "term": "1c53f048e3a74984b2a93af175e24e87"
    },
    {
      "act": "ECHO",
      "data": "touch essai",
      "term": "1c53f048e3a74984b2a93af175e24e87"
...
}

Quand vous voulez rejouer la session :

pias play fichier_d_enregistrement

Par défaut il faut appuyer sur une touche quelconque du clavier pour voir apparaitre chaque caractère, donnant l’impression que vous êtes un hacker de Hollywood. C’est rigolo, mais parfaitement chiant à la longue. On peut faire jouer la session automatiquement avec l’option --auto-type qui va taper chaque ligne automatiquement. Il suffira alors d’appuyer sur entrée à chaque ligne pour avoir le résultat suivant. C’est mon mode préféré.

Si vous êtes un gros feignant, vous pouvez tout jouer en automatique en rajoutant l’option --auto-waypoint qui va vous dispenser de taper entrée à chaque fin de ligne. Ex :

pias play ex1 --auto-type --auto-waypoint

La session jouée est simulée. Elle n’a aucun impacte sur le système. Si vous faites un mkdir dans bash ou un shutil.rmtree dans python, ça ne fera rien.

Néanmoins, parfois il est utile d’avoir le effets réels des commandes. Dans ce cas on peut utiliser --live-replay. Attention, faites bien gaffe à ce que vous allez jouer…

playitagainsam est intéressant pour tout ce qui est formation et tutorial, d’autant plus qu’il existe un player javascript pour faire la démonstration de vos sessions shell sur un blog ou un slideshow.

]]>
http://sametmax.com/rejouer-un-session-de-terminal-avec-playitagainsam/feed/ 10 10298
Remplacer sed, awk, cut et Perl par Python (= orgasme pour sysadmin) http://sametmax.com/remplacer-sed-awk-cut-et-perl-par-python-orgasme-pour-sysadmin/ http://sametmax.com/remplacer-sed-awk-cut-et-perl-par-python-orgasme-pour-sysadmin/#comments Sat, 14 Dec 2013 08:28:41 +0000 http://sametmax.com/?p=8261 La force de Perl c’est qu’il permettait de piper des données directement via la ligne de commande pour faire des manipulations rapides.

C’est pour cela que c’était devenu les choix des sysadmins. Parce que jusqu’ici, le choix c’était soit de faire un truc simple en connaissant par coeur la tool box GNU, soit ouvrir un fichier et faire un script.

Python ne permet pas de piper des données directement dans la commande, mais des projets ont vu le jour pour le faire.

Il y a le projet pyp, que l’on doit à Sony Pictures Imageworks qui avait besoin de se simplifier l’automatisation des tâches de build pour ses films.

Et il y a pyped, dont j’avais brièvement parlé ici (article qui mérite d’être mis à jour vu que j’ai remplace dateutils par arrow).

Les deux étaient sympas, mais avait des syntaxes alambiquées, n’étaient pas compatibles python 3 et manquaient d’imports auto. Cependant, pyped est récemment passé en v1.0, donc stable, et a une toute nouvelle approche de syntaxe qui rend la bestiole super agréable à utiliser.

Présentation.

Stdin, ligne à ligne

L’installation est bateau, c’est du pip :

pip install --user pyped

Et derrière, on obtient la commande pyp. Elle s’utilise essentiellement à la suite d’une autre commande. Typiquement :

cat /etc/fsta | pyp "un truc"

L’astuce, c’est que “un truc” peut être n’importe quelle expression Python. Généralement une expression qui print() quelque chose.

Or, Pyped met automatiquement à disposition de cette expression deux variables :

  • La ligne en cours, dans la variable x.
  • Le numéro de la ligne en cours, dans la variable i.

L’expression Python est appelée une fois pour chaque ligne.

Par exemple, supposons que j’ai un fichier “fortune.txt” contenant :

bitcoin (btc) : 5
euros (€) : 100
dollars ($) : 80

Si je veut tout mettre en majuscule, je fais :

$ cat fortune.txt | pyp "print(x.upper())"
BITCOIN (BTC) : 5
EUROS (€) : 100
DOLLARS ($) : 80

On peut mettre plusieurs expressions d’affilé. Ainsi, si je veux récupérer la somme et le symbole uniquement :

$ cat fortune.txt | pyp "devise, sign, _, value = x.split()" "sign = sign.strip('()')" "print('%s%s' % (value, sign))"
5btc
100€
80$

Ok, c’est plus long que perl, mais vachement plus facile à écrire et à relire. Et j’utilise un langage que je connais déjà. Et pas besoin de faire un mix incompréhensible de sed, awk et autre cut.

Si j’ai vraiment besoin de lisibilité, je peux même le mettre sur plusieurs lignes :

$ cat fortune.txt | pyp "                                                                                                 
devise, sign, _, value = x.split() 
sign = sign.strip('()') 
print('%s%s' % (value, sign))  
"
5btc
100€
80$

Vous aurez noté que j’utilise print() et que je semble ne pas me soucier de l’unicode. C’est parceque pyped fait ça au début du script :

from __future__ import print_function, unicode_literals, division, absolute_imports

Du coup, on est bien en Python 2.7, mais on bénéficie de la division améliorée, de la fonction pour printer, des imports absolus et surtout, de l’unicode partout. D’ailleurs pyped vous transforme x pour que ce soit un objet unicode.

Dans tous les cas, pyped est compatible Python 3.

Tout traiter d’un coup

Parfois, on a besoin d’avoir accès à toutes les lignes, pas juste les lignes une à une. pyped permet cela avec l’option -i. Les variables x et i disparaissent au profit de la variable l, qui contient un itérable sur toutes les lignes.

Par exemple, envie de trier tout ça ?

cat fortune.txt | pyp -i "
lignes = (x.split() for x in l)
lignes = sorted((v, s.strip('()')) for d, s, _, v in lignes)
for ligne in lignes: print('%s%s' % ligne)
"
100€
5btc
80$

Moar options

Lisez la doc, car il y a d’autres options du genre éviter que pyped vous strip automatiquement le ligne break, forcer l’encoding, etc.

Parmi les trucs les plus utiles, il y a l’option -b qui permet de lancer un code avant la boucle. Pratique pour importer des trucs genre le module tarfile pour extraire une archive avant d’utiliser son contenu.

Néanmoins la plupart du temps on a rien besoin d’importer car pyped importe déjà automatiquement les modules les plus utiles : maths, datetime, re, json, hashlib, uuid, etc.

]]>
http://sametmax.com/remplacer-sed-awk-cut-et-perl-par-python-orgasme-pour-sysadmin/feed/ 27 8261
Variables d’environnement utilisées par Python http://sametmax.com/variables-denvironnement-utilisees-par-python/ http://sametmax.com/variables-denvironnement-utilisees-par-python/#comments Wed, 31 Jul 2013 15:07:36 +0000 http://sametmax.com/?p=6987 Avant même l’utilisation d’options, de fichiers de conf, et outils installés, les variables d’environnement sont un moyen pratique de configurer un programme. Il s’agit simplement d’une variable globale accessible dans le shell courant.

Par exemple, sous bash, pour créer une variable, il suffit de faire :

$ NOMDEVARIABLE='valeur' # mettre la variable à la bonne valeur
$ export NOMDEVARIABLE # rendre la variable globale

La convention est de mettre leur nom en majuscule.

Et pour afficher la variable, il suffit de faire :

$ echo $NOMDEVARIABLE
valeur

Pourquoi c’est pratique ? Et bien parce qu’un programme comme Python va aussi aller regarder dans ces variables d’environnement pour se configurer. Donc, si vous settez la variable avec le bon nom dans votre shell et que vous lancez l’interpréteur Python, vous pouvez démarrer ce dernier avec un comportement différent, comme le ferait une option ou un fichier de config. La différence ? La variable est valable pour toute la session de shell, donc même si vous ressortez de l’interpréteur Python, et que vous le relancez, tant que vous êtes dans la même session de shell, la configuration reste la même.

Variables attendues

PYTHONSTARTUP: un module à exécuter au démarrage de Python.

Pratique si vous savez que vous allez utiliser souvent le même code dans votre prochaine session de travail avec le shell. Par exemple, je crée un module /tmp/imports.py et je met dedans :

import json
import pickle
from datetime import datetime

Ensuite, je set ma variable :

$ PYTHONSTARTUP='/tmp/imports.py' 
$ export PYTHONSTARTUP 

Et en lançant l’interpréteur, même en sortant et en le relançant 50 fois de suite, je n’ai pas à importer ces modules.

PYTHONPATH : une liste de dossiers séparés par ‘:’ qui va être ajouté à sys.path

Vous savez qu’il y a des packages qui ne sont pas dans le PYTHON PATH, donc non importables. Mais pour le moment, vous voulez les utiliser quand même pour faire des tests vite fait (vous corrigerez le problème plus tard ^^).

Facile:

PYTHONPATH='/home/sam/un_dossier_qui_contient_mes_libs:/home/sam/projects/autre_projet'
export $PYTHONPATH

Et voilà, tout ce qui est dans ces deux dossiers est importable.

Il y a encore :

PYTHONHOME : choisir un autre dossier dans lequel chercher l’interpréteur Python.
PYTHONCASEOK : ingorer la casse dans le nom des modules sous Windows
PYTHONIOENCODING : forcer un encoding par défaut pour stdin/stdout/stderr
PYTHONHASHSEED : changer la seed hash() (renforce la sécurité de la VM)

Variables d’environnement permanentes

Les programmes Python utilisent beaucoup les variables d’environnement : Django, Celery, nose, virtualenv, pip… Tous peuvent être aussi configurés avec ces variables.

Parfois, on voudra que cette variable soit accessible depuis tous les shells, et même après le reboot. Bref, rendre la configuration permanente.

Il y a plusieurs solutions. L’une est de mettre la déclaration de la variable dans le script de démarrage de votre shell, par exemple sous bash, de mettre la variable dans .bashrc.

Ainsi, j’ai des entrées comme celle-ci dans mon .bashrc :

# évite à pip de télécharger plusieurs fois la même lib à la réinstallation
PIP_DOWNLOAD_CACHE='/opt/pip-cache';
export PIP_DOWNLOAD_CACHE;

Une autre est de la mettre dans un hook, c’est à dire un script exécuté à un moment donné par un programme. De nombreux programmes ont des hooks, et il y a des exemples sur le blog pour virtualenv et git.

Variables d’environnement personnalisées

Vos propres programmes peuvent lire (pour se configurer) et écrire (pour configurer d’autres programme ou forcer leur propre configuration en cas de multiprocessing) des variables d’environnement. Il suffit de faire :

>>> import os
>>> os.environ
{'LC_NUMERIC': 'fr_FR.UTF-8', 'gs_max_changes': '99', 'scmbDir': '/home/sam/.scm_breeze', 'GNOME_DESKTOP_SESSION_ID': 'this-is-deprecated', 'AUTOJUMP_DATA_DIR': '/home/sam/.local/share/autojump', 'LC_IDENTIFICATION': 'fr_FR.UTF-8', 'XDG_CURRENT_DESKTOP': 'Unity', 'GNOME_KEYRING_PID': '2787', 'LOGNAME': 'sam', 'USER': 'sam', 'PROMPT_COMMAND': 'set_bash_prompt;preexec_invoke_cmd', 'PATH': '/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games', 'LC_PAPER': 'fr_FR.UTF-8', 'GNOME_KEYRING_CONTROL': '/home/sam/.cache/keyring-1rkOf1', 'design_av_dirs': 'Animations Videos Flash Music Samples', 'DISPLAY': ':0', 'SSH_AGENT_PID': '2849', 'LANG': 'fr_FR.UTF-8', 'TERM': 'xterm', 'SHELL': '/bin/bash', 'XDG_SESSION_PATH': '/org/freedesktop/DisplayManager/Session0', 'XDG_SESSION_COOKIE': 'ccef8e8a757563a3c14c304f00000003-1375177738.724796-1812587231', 'LANGUAGE': 'fr_FR:fr_CA:en', 'SESSION_MANAGER': 'local/sam:@/tmp/.ICE-unix/2798,unix/sam:/tmp/.ICE-unix/2798', 'LC_MONETARY': 'fr_FR.UTF-8', 'LESSCLOSE': '/usr/bin/lesspipe %s %s', 'MANDATORY_PATH': '/usr/share/gconf/ubuntu.mandatory.path', 'DBUS_SESSION_BUS_ADDRESS': 'unix:abstract=/tmp/dbus-4sjzHNl8JS,guid=6ea6a72c49faf1630800018', 'VIRTUALENVWRAPPER_LOG_DIR': '/home/sam/.virtualenvs', 'COMPIZ_CONFIG_PROFILE': 'ubuntu', 'EDITOR': '/usr/bin/textadept', 'DESKTOP_AUTOSTART_ID': '10b40d4ebf3d1cf3fd700000027980010', 'GPG_AGENT_INFO': '/home/sam/.cache/keyring-1rkOf1/gpg:0:1', 'HOME': '/home/sam', 'WORKON_HOME': '/home/sam/.virtualenvs', 'SHLVL': '1', 'SSH_AUTH_SOCK': '/home/sam/.cache/keyring-1rkOf1/ssh', 'VIRTUALENVWRAPPER_HOOK_DIR': '/home/sam/.virtualenvs', 'LC_ADDRESS': 'fr_FR.UTF-8', 'COMP_WORDBREAKS': ' \t\n"\'><;|&(:', 'root_design_dir': '/home/sam/Dropbox/Design', 'GDMSESSION': 'ubuntu', 'project_design_dir': 'design_assets', 'git_status_command': 'git_status_shortcuts', 'XDG_SEAT_PATH': '/org/freedesktop/DisplayManager/Seat0', 'LC_ALL': 'fr_FR.UTF-8', 'LESSOPEN': '| /usr/bin/lesspipe %s', 'git_env_char': 'e', '_': '/usr/bin/python', 'DEFAULTS_PATH': '/usr/share/gconf/ubuntu.default.path', 'VIRTUALENVWRAPPER_PROJECT_FILENAME': '.project', 'DESKTOP_SESSION': 'ubuntu', 'GIT_REPO_DIR': '/home/sam/Work', 'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/etc/xdg', 'GTK_MODULES': 'canberra-gtk-module:canberra-gtk-module', 'UBUNTU_MENUPROXY': 'libappmenu.so', 'AUTOJUMP_HOME': '/home/sam', 'LC_TELEPHONE': 'fr_FR.UTF-8', 'XAUTHORITY': '/home/sam/.Xauthority', 'LC_MEASUREMENT': 'fr_FR.UTF-8', 'PWD': '/home/sam', 'PIP_DOWNLOAD_CACHE': '/opt/pip-cache', 'design_ext_dirs': 'Fonts IconSets', 'ga_auto_remove': 'yes', 'LC_NAME': 'fr_FR.UTF-8', 'design_base_dirs': 'Images Backgrounds Logos Icons Mockups Screenshots', 'LC_TIME': 'fr_FR.UTF-8', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:', 'XDG_DATA_DIRS': '/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/', 'GIT_REPOS': ''}

C'est un simple dico dans lequel vous pouvez lire et écrire. Comme vous pouvez le voir, il ne s'agit pas juste des variables qui concernent Python mais de toutes celle de la session, donc attention, de grands pouvoirs impliquent de grandes possibilités de merder.

]]>
http://sametmax.com/variables-denvironnement-utilisees-par-python/feed/ 10 6987
Historique bash récent http://sametmax.com/historique-bash-recent/ http://sametmax.com/historique-bash-recent/#comments Thu, 11 Apr 2013 12:23:52 +0000 http://sametmax.com/?p=5683 PyDanny en affichant ici mon historique des commandes les plus utilisées.]]> Je plagie PyDanny en affichant ici mon historique des commandes les plus utilisées récupéré grâce à :

$ history | awk '{a[$2]++ } END{for(i in a){print a[i] " " i}}'|sort -rn |head -n 20

L’exercice consiste à commenter chaque entrée, donc acte :

100 ./manage.py # Jamie Foxx
71 sudo         # Make me a sandwich (then apt-get upgrade)
56 cd           # j'ai beaucoup de projets différents
41 ipython      # Voilà ce que c'est d'être dev Python...
40 ssh          # ... sur des projets Web
37 py.test      # Ben oui, je fais des tests !
37 ls           # Comment ça IOError ?
34 gs           # Alias de Git status :-)
26 ga           # Merveilleux SCMBreeze, installez le
24 pip          # requests, ipdb, path.py, peewee...
24 co           # git commit -m "`echo "$*" | sed -e 's/^./\U&\E/g'`"
22 vi           # Presque que pour les config d'nginx
21 python       # Quand je fais des tests pour le blog
17 [censored]   # Le nom d'un projet de site de Cul
15 workon       # Ca devrait être + élévé, mais j'ai ajouté l'autovirtualenv 
15 grin         # J'aime pas "rechercher dans tous les fichiers" sur ST2
11 tail         # Une longue session de debuggage via log d'erreurs
10 ipython3     # Migration vers Python 3 en cours
9 wget          # Pas envie de toucher ma souris
]]>
http://sametmax.com/historique-bash-recent/feed/ 8 5683
Invalid cross-device link http://sametmax.com/invalid-cross-device-link/ http://sametmax.com/invalid-cross-device-link/#comments Tue, 09 Apr 2013 10:19:57 +0000 http://sametmax.com/?p=5652 Les erreurs d’upload de fichier, c’est 99% de problèmes de droit d’accès et d’espace disque. Mais de temps à autres, on tombe sur des petites saloperies bien vicelardes comme ce code anodin :

os.rename(uploaded_tmp_file, destination)

Ce snippet, comme vous l’aurez compris, prend simplement un fichier qui vient d’être uploadé et le déplace vers un autre dossier où il sera traité, chouchouté, encodé, et mis en ligne.

Sauf que la ligne en question nous a valu un cryptique :

IOError: Invalid cross-device link

PDB nous confirme le merdier, même en le faisant à la main. Pourtant la commande bash MV fait le déplacement du fichier sans problème.

User / group ? Checked.

Permission en lecture écriture ? Checked.

SEL linux ? Désactivé depuis longtemps.

Quid alors ?

Les archives de la mailling list de Python nous offre une réponse à la question, que je vous traduis :

mv est un programme étonnamment complexe, tandis que os.rename est un wrapper autour de rename(2) qui est probablement documenté sur ton système comme retournant EXDEV dans ces circonstances.

os.xxx est généralement une surcouche assez fine autour de ce que ton OS fournit, et en hérite toutes les limites. Pour certains actions, os.shutil fournit quelque chose qui se situe entre os.xxx et os.system(“xxx”) en terme de complexité et de capacité.

Je l’ai traduis en français, maintenant je vous la refais en langage humain : os.rename ne fait vaguement qu’appeler la commande rename, qui n’est pas très puissante, et notamment qui est incapable de gérer un déplacement de fichier d’une partition à une autre. Or dans notre cas, notre dossier temporaire était sur une partition séparée pour des raisons de perfs.

La solution est d’utiliser shutil, un module un peu plus lent, mais surtout de plus haut niveau qui se charge des détails comme la nature et l’origine du fichier et de sa destination.

Bref, la solution est tout simplement de faire :

shutil.move(uploaded_tmp_file, destination)

Tout ça pour ça, oui, mais c’est ce qui arrive quand une abstraction ne fait plus son boulot dans un langage de haut niveau où on a l’habitude que tout soit automatisé.

]]>
http://sametmax.com/invalid-cross-device-link/feed/ 3 5652
Set -e for the win http://sametmax.com/set-e-for-the-win/ http://sametmax.com/set-e-for-the-win/#comments Thu, 14 Mar 2013 08:26:52 +0000 http://sametmax.com/?p=5408 10 ans plus tard, je découvre cette option pour les scripts bash.

Voyez vous, quand on écrit un script bash, il exécute les commandes ligne à ligne. Si il y en a une qui retourne une erreur, il continue vaillamment.

Sur un script où chaque ligne dépend de la précédente (comme un script de déploiement), c’est moyen.

Pour y pallier, il suffit de mettre tout en haut du script :

set -e 

Et voilà. Si une commande retourne une erreur, le script s’arrête à ce niveau. 10 ans de Linux et je découvre ça maintenant. Moi content.

]]>
http://sametmax.com/set-e-for-the-win/feed/ 7 5408
A l’intérieur de mon .bashrc http://sametmax.com/a-linterieur-de-mon-bashrc/ http://sametmax.com/a-linterieur-de-mon-bashrc/#comments Tue, 22 Jan 2013 10:26:44 +0000 http://sametmax.com/?p=4238 .bashrc donne rapidement lieu dans les comments à un concours de celui qui a la plus longue (jusqu'à ce qu'arrive un utilisateur de zsh, et alors commence le concours de celui qui pisse le plus loin). Mais bon, aujourd'hui j'ai la flemme d'écrire un article complet.]]> Généralement montrer son .bashrc donne rapidement lieu dans les comments à un concours de celui qui a la plus longue (jusqu’à ce qu’arrive un utilisateur de zsh, et alors commence le concours de celui qui pisse le plus loin). Mais bon, aujourd’hui j’ai la flemme d’écrire un article complet.

Rappel : le .bashrc c’est le fichier qui est automatiquement chargé au démarrage du shell bash, le shell par défaut sur la plupart des Unix incluant Mac et Ubuntu.

Donc si vous voulez avoir une expérience de travail personnalisée dans votre terminal, c’est dans ce fichier que ça se passe.

Personnellement, j’ai tout le bordel que met Ubuntu par défaut (notamment les trucs avec les autocomplétions de partout). En en prime je rajoute :

# un raccourcis pour lancer Redis car je le met sur off par défaut mais je le 
# lance souvent

function redis {
    if [ ! -e "/var/run/redis/redis-server.pid" ] ; then
        sudo service redis-server start
    fi
}

# un tas de raccourcis type

function projet_django {
    workon projet_django;
    cd /home/sam/Work/projet_django/repo/projet_django;

    if [[ $# -ne 0 ]]; then
        ./manage.py $@
    fi
}
alias sb='projet_django'

# CF: http://sametmax.com/un-alias-bash-pour-django-virtualenv-dont-je-ne-peux-plus-me-passer/


# fonction fétiche de bourrin

function killbill {
    BAK=$IFS
    IFS=$'\n'
    for id in $(ps aux | grep -P -i $1 | grep -v "grep" | awk '{printf $2" "; for (i=11; i
]]>
			http://sametmax.com/a-linterieur-de-mon-bashrc/feed/
		24
	4238