====== Demo Voyage ====== \ \/ /___ __ __ ___ ___ ___ Useful Commands: \ // _ \\ \/ /,-_ |/ _ |/ -_) remountrw - mount disk as read-write \/ \___/ \ / \___,\_ |\___| remountro - mount disk as read-only _/_/ _'_| remove.docs - remove all docs and manpages { V o y a g e } - L i n u x < http://linux.voyage.hk > Version: 0.9.2 (Build Date 20131219) **Version: 0.9.2 (Build Date 20131219)** ====== Voyage box quickstart ====== ===== Alix box: GPS demonstration===== host: imavoyage-alix.local WLAN: pwd alarm-dtn-thuy Serial 115200 8N1 root pwd voyage eth0 is on the right, when facing the ports. Demo software: ima_ws/ima-carpc_gpsdemo_voyage/src/carpcd ./carpcd -c carpcd_demo.conf & ** Turn off dnsmasq!!! on intranet iface ** ===== OpenVox box NFC demo ===== host imavoyage root pwd voyage eth0 is on the left, when facing the ports. Demo software: nfcclient ====== Software Features ====== **Current Voyage version based on Debian Wheezy 7.4 (deb7u4)** so use wheezy to compile packages. **Can deb7u8 7.8 package be installed on 7.4???** Maybe ===== DTN with IBR-DTN ===== **We use viersion 0.12.1** ==== Run ibr-dtn ==== === /etc/init.d/ibrdtnd === If ibrdtnd is installed from source, fix the binary path to /usr/local/{sbin,etc} 15 PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin 16 DESC=ibrdtnd # Introduce a short description here 17 NAME=ibrdtnd # Introduce the short server's name here 18 PNAME=dtnd # Introduce the process name 19 DAEMON=/usr/local/sbin/dtnd # Introduce the server's location here 20 PIDFILE=/var/run/ibrdtn/$PNAME.pid # Path where the pid file is stored 21 SCRIPTNAME=/etc/init.d/$NAME # Name of this script 22 DAEMON_ARGS="-D -p ${PIDFILE}" # Arguments to run the daemon with === Config default /etc/default/ibrdtn === # Additional options that are passed to the Daemon. #DAEMON_OPTS="-c /etc/ibrdtn/ibrdtnd.conf" DAEMON_OPTS="-c /usr/local/etc/ima_ibrdtnd.conf" # Directory for additional configuration, e.g. security keys and certificates DAEMON_CONFDIR="/usr/local/etc/ibrdtn" === Conf File /usr/local/etc/ima_ibrdtnd.conf === egrep -v "^(#|$)" /usr/local/etc/ima_ibrdtnd.conf local_uri = dtn://imarsu logfile = /var/log/ibrdtn/ibrdtn.log discovery_address = ff02::142 224.0.0.142 net_lan0_type = tcp # we want to use TCP as protocol net_lan0_interface = wlan0 # listen on interface eth0 net_lan0_port = 4556 # with port 4556 (default) net_interfaces = lan0 routing = flooding security_path = /etc/ibrdtn/bpsec security_trusted_ca_path = /etc/ibrdtn/certs === Run ibrdtn at startup === Test the script: insserv -n ibrdtn Install the script insserv ibrdtn ==== Compile IBR-DTN ==== === Reference === * Install from source: http://trac.ibr.cs.tu-bs.de/project-cm-2012-ibrdtn/wiki/source **Use git repo is more convenient** === Script to download gzipped Source === 1. Define CONOPTS with a default var!. Empty var may cause problem: zero + "text" = zero Disable all the --with-blah VERSION=1.0.1 REPOSITORY=http://www.ibr.cs.tu-bs.de/projects/ibr-dtn/releases MODULES="ibrcommon ibrdtn ibrdtnd ibrdtn-tools" CONFOPTS="--enable-shared=yes " 2. Bug: change [ "${MOD}" **==** "ibrcommon" ] to [ "${MOD}" **=** Ubuntu does not like this CONFOPTS+="--with-ibrcommon=$(pwd)/ibrcommon-${VERSION} " Change to **CONFOPTS="${CONFOPTS} --with-ibrcommon=$(pwd)/ibrcommon-${VERSION} "** if [ "${MOD}" == "ibrcommon" ]; then <-------- bug here CONFOPTS+="--with-ibrcommon=$(pwd)/ibrcommon-${VERSION} " #CONFOPTS+="--with-ibrcommon=$(pwd)/prefix " fi if [ "${MOD}" == "ibrdtn" ]; then CONFOPTS+="--with-ibrdtn=$(pwd)/ibrdtn-${VERSION} " #CONFOPTS+="--with-ibrdtn=$(pwd)/prefix " fi ====== . ====== === GIT repository === **USE THIS METHOD** Have a look at the README-file in ibrdtn/, it gives you a list of packages to install. If you like to work with the bleeding edge of the source code then you can checkout the GIT repository. A public summary of the repository is available on ​github.com/ibrdtn. A short clone + configuration + compilation + installation goes like this: git clone https://github.com/ibrdtn/ibrdtn.git ibrdtn-repo cd ibrdtn-repo/ibrdtn bash autogen.sh ./configure make sudo make install * http://localhost/wiki/doku.php?id=work_dai_labor:projects:ima:ima_ws:dtn:ibr_dtn ====== . ====== === Disable BSP security feature === cd ibrdtn-1.0.1 vim configure.ac # look for BSP and disable # change 1 to 0 103 AC_DEFINE(IBRDTN_SUPPORT_BSP, [0], [bundle security protocol supported]) 104 AC_DEFINE(HAVE_OPENSSL, [0], []) ibrdtnd auto detect that they are disabled. ====== . ====== === Build Debian packages === Install all required packages using apt-get. sudo apt-get install devscripts build-essential cdbs pkg-config debhelper autotools-dev libnl-3-dev \ libnl-genl-3-dev libnl-route-3-dev libnl-nf-3-dev libnl-cli-3-dev libssl-dev libssl-dev zlib1g-dev \ libsqlite3-dev libcurl4-openssl-dev libdaemon-dev libvmime-dev libarchive-dev Download all archives (ibrcommon, ibrdtn, ibrdtnd, ibrdtn-tools) to a build folder and extract them. Then change into each source folder and build the package using this command. debuild -i -us -uc -b If previous build failed, add -d to overwrite: debuild -i -us -uc -b -d === Check Build Dependencies === cd SOURCE_DIR dpkg-checkbuilddeps Install the required package Ref: * http://debian-handbook.info/browse/wheezy/sect.setup-apt-package-repository.html * https://wiki.debian.org/IntroDebianPackaging ==== Config ibrdtn ==== **Voyage install everything in /usr/local/ ** === /usr/local/etc/ibrdtn.conf === interface eth0 forward flooding dtnd -d 9 -c /usr/local/etc/ibrdtn.conf ===== ibrdtn-imaapp ===== Checkout code: svn checkout https://cvs.dai-labor.de/svn/dang/ima_pj/openwrt-feed/branches/x86_64_dev/packages Dependency: libboost >= 1.34.0 apt-cache search libboost apt-get install libboost-dev libboost-date-time1.49.0 libboost-thread1.49.0 \ libboost-date-time-dev libboost-thread-dev libboost-system-dev **Dependency ima: libdaiutil, liboonet, yajl** Also install them. Compile ./autogen.sh ./configure make install ==== Configure dtnimaapp ==== which dtnimaapp.conf /usr/local/bin/dtnimaapp.conf root@imavoyage:~/ima_ws/dtn_ws/ibr-dtn_ws/ima_carpc_dev/packages/ibrdtn-imaapp# mv /usr/local/bin/dtnimaapp.conf /usr/local/etc/ dtnimaapp -c /usr/local/etc/dtnimaapp.conf ==== /etc/init.d/dtnimaapp ==== ==== /etc/default/dtnimaapp ==== **Copy from ibrdtnd** ===== Startup script ===== * http://www.linux.com/news/enterprise/systems-management/8116-an-introduction-to-services-runlevels-and-rcd-scripts * https://www.debian-administration.org/articles/28 * http://ubuntuforums.org/showthread.php?t=1899664 cp /etc/init.d/skeleton /etc/init.d/nfcclient chmod +x /etc/init.d/nfcclient vim /etc/init.d/nfcclient ln -s /etc/init.d/nfcclient /etc/rc4.d/S18nfcclient # see cat /etc/rc4.d/README # obsolate: update-rc.d script defaults You should be using insserv linknx find /etc/rc?.d|grep nfc And not update-rc.d linknx defaults As of Debian 6.0 (Squeeze), update-rc.d has been replaced with insserv (see here). Why? Because 6.0 introduced a new boot process, for which you have the headers in place (the INIT INFO section at the top of the script). === Working solution === Add the code below to your script in /etc/init.d, modify it to your needs, run insserv -n scriptname to verify that it will work, insserv -n scriptname then run insserv scriptname to make it all happen! insserv scriptname ### BEGIN INIT INFO # Provides: scriptname <-------- IMPORTANT! # Required-Start: $all $ibrdtnd # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Short script description # Description: Longer script description. ### END INIT INFO ==== Daemonize foreground program ==== add -b -m: /sbin/start-stop-daemon --start ...-p $PIDFILE -b -m ... -exec ==== Modifying stop script ==== There is two ways: The first is just to specify a numeric --retry value. Then it will use /signal/timeout/KILL/timeoutschedule. I.e. send a terminating signal (specified with--signal` option), then wait the specified number of seconds and then send a KILL signal that could not be ignored by a process and therefore it will be forced to exit. The command will look like: /sbin/start-stop-daemon --stop --signal TERM --retry 5 --quiet --oknodo --pidfile /var/run/redis/redis.pid --exec /usr/bin/redis-server The second is to specify a complete schedule to the --retry option. It will look like: /sbin/start-stop-daemon --stop --retry TERM/5/KILL/10 --quiet --oknodo --pidfile /var/run/redis/redis.pid --exec /usr/bin/redis-server ==== Start daemon with log ==== To expand on ypocat's answer, since it won't let me comment: start-stop-daemon --start --quiet --chuid $DAEMONUSER \ --make-pidfile --pidfile $PIDFILE --background \ --startas /bin/bash -- -c "exec $DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1" Using 'exec' to run the daemon allows stop to correctly stop the child process instead of just the bash parent. Using --startas instead of --exec ensures that the process will be correctly detected by its pid and won't erroneously start multiple instances of the daemon if start is called multiple times. Otherwise, start-stop-daemon will look for a /bin/bash process and ignore the actual child process running the daemon. ====== OS Settings ====== ===== Networking ===== eth0 as WAN link with dhcp ===== WiFi Interface ===== Install wifi drivers **The kernel should have drivers if compiled correctly. No user space firmware needed!!!** firmware-linux-free - Binary firmware for various drivers in the Linux kernel firmware-atheros - Binary firmware for Atheros wireless cards apt-get install firmware-atheros ===== Network interfaces ===== ===== Setup WiFi Access Point ===== * https://wireless.wiki.kernel.org/en/users/drivers/ath9k/spectral_scan?s[]=ar9300 * http://seravo.fi/2014/create-wireless-access-point-hostapd * http://svn.voyage.hk/repos/voyage/branches/voyage-live/0.9.2/config/includes.chroot/README * Good: http://www.3open.org/d/voyage/setup_networking These should be installed apt-get install bridge-utils wireless-tools hostapd Hostap & Dnsmasq sudo apt-get install hostapd dnsmasq ==== Network Interface Configuration /etc/network/interfaces ==== Bridge br0 has IP and listen to dhcp request. eth1, wlan0 are 2 ports connecting LAN hosts. auto lo iface lo inet loopback ## WAN interface auto eth0 iface eth0 inet dhcp ## Bridge for LAN # LAN ip_addr is assigned to bridge. add wlan0 and eth1 as prots auto br0 eth1 iface eth1 inet manual up ifconfig eth1 0.0.0.0 up down ifconfig eth1 down auto wlan0 iface wlan0 inet static address 2.0.0.2 netmask 255.255.255.0 up iwconfig wlan0 txpower 19 hostapd /etc/hostapd/hostapd.wlan0.conf iface br0 inet static address 2.0.0.1 netmask 255.255.255.0 network 2.0.0.0 broadcast 2.0.0.255 # gateway 192.168.1.1 # wlan0 is added using hostapd*.conf (bridge=br0) bridge_ports eth1 up nat.sh br0 eth0 "2.0.0.0/24" ==== /etc/hostapd/hostapd.wlan0.conf ==== cat /etc/hostapd/hostapd.wlan0.conf bridge=br0 interface=wlan0 driver=nl80211 logger_syslog=-1 logger_syslog_level=2 logger_stdout=-1 logger_stdout_level=2 debug=4 #dump_file=/tmp/hostapd.dump ctrl_interface=/var/run/hostapd.wlan0 ctrl_interface_group=0 channel=6 hw_mode=g macaddr_acl=0 auth_algs=3 eapol_key_index_workaround=0 eap_server=0 wpa=3 ssid=IMARSU-APv wpa_passphrase=imarsuvoyage wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP #eapol_version=1 #wme_enabled=1 #ieee80211n=1 #ht_capab=[HT40-][HT40+][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CCK-40] ==== DNSMASQ ==== cat /etc/dnsmasq.more.conf # dhcp-range=wlan0,10.1.10.10,10.1.10.250,24h # dhcp-range=eth1,10.1.20.10,10.1.20.250,24h # dhcp-range=eth2,10.1.30.10,10.1.30.250,24h # dhcp-range=eth3,10.1.40.10,10.1.40.250,24h # dhcp-leasefile=/var/tmp/dnsmasq.leases bind-interfaces interface=lo,br0,eth0 no-dhcp-interface=lo,eth0 dhcp-range=2.0.0.20,2.0.0.200,255.255.255.0,12h #except-interface=eth0 ==== Enable Forwarding /etc/sysctl.conf ==== net.ipv4.ip_forward=1 ==== Enable NAT rules for LAN subnet /etc/rc.local ==== iptables -t nat -A POSTROUTING -s 192.168.8.0/24 ! -d 192.168.8.0/24 -j MASQUERADE There is a script to setup NAT which can be called from interfaces === /usr/local/sbin/nat.sh === cat /usr/local/sbin/nat.sh #!/bin/sh if [ -z $1 ] || [ -z $2 ] || [ -z $3 ] ; then echo "$0 " exit fi iptables -t nat -N "$1"-NAT 2>/dev/null iptables -t nat -F "$1"-NAT iptables -t nat -D POSTROUTING -j "$1"-NAT 2>/dev/null iptables -t nat -A POSTROUTING -j "$1"-NAT iptables -t nat -D "$1"-NAT -j MASQUERADE 2>/dev/null iptables -t nat -A "$1"-NAT -o "$2" -s "$3" -j MASQUERADE # Testing : used for integration with nocat iptables -N "$1"-FORWARD 2>/dev/null iptables -F "$1"-FORWARD iptables -D "$1"-FORWARD -j ACCEPT -s "$3" 2>/dev/null iptables -A "$1"-FORWARD -j ACCEPT -s "$3" iptables -D FORWARD -j "$1"-FORWARD -s "$3" 2>/dev/null iptables -I FORWARD 1 -j "$1"-FORWARD -s "$3" iptables -N "$1"-INBOUND 2>/dev/null iptables -F "$1"-INBOUND iptables -D "$1"-INBONUD -j ACCEPT -d "$3" 2>/dev/null iptables -A "$1"-INBOUND -j ACCEPT -d "$3" iptables -D FORWARD -j "$1"-INBOUND -d "$3" 2>/dev/null ==== Multicast ==== http://unix.stackexchange.com/questions/25872/how-can-i-know-if-ip-multicast-is-enabled Enable Mcast ping echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts ====== . ====== root@alarm-dtn-thuy:~/ima/libnfc-1.7.0# cat /etc/network/interfaces # Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or # /usr/share/doc/ifupdown/examples for more information. auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp # mac80211-based drivers auto wlan0 iface wlan0 inet static address 172.16.142.1 netmask 255.255.255.0 broadcast 172.16.142.255 hostapd /etc/hostapd/hostapd.wlan0.conf up nat.sh wlan0 eth0 "172.16.142.0/24" auto wlan1 iface wlan1 inet manual wireless-mode ad-hoc wireless-channel 1 wireless-essid alarm-adhoc-dtn #up avahi-autoipd -k wlan1 up avahi-autoipd -D wlan1 up ip r a 169.254.0.0/16 dev wlan1 metric 99 up ip r a default dev wlan1 metric 99 up ip r a 224.0.0.0/4 dev wlan1 post-down avahi-autoipd -k wlan1 #up route add -net 169.254.0.0 netmask 255.255.0.0 dev wlan1 metric 99 #up route add default dev wlan1 metric 99 #address 10.1.20.1 #netmask 255.255.255.0 #broadcast 10.1.20.255 #hostapd /etc/hostapd/hostapd.wlan1.conf #up nat.sh wlan1 eth0 "10.1.20.0/24" ====== Voyage Customized Installation ====== * http://localhost/wiki/doku.php?id=work_dai_labor:projects:ima:ima_ws:car_pc:voyage_linux:compile_kernel * http://svn.voyage.hk/repos/voyage/branches/voyage-live/0.6.0/config/chroot_local-includes/README * http://linux.voyage.hk/ ====== Recompile kernel with different options ====== ===== CONFIG_POSIX_MQUEUE is required for mqueue but not set by default. ===== grep CONFIG_POSIX_MQUEUE /boot/config-3.10.11-voyage # CONFIG_POSIX_MQUEUE is not set mkdir /dev/mqueue mount -t mqueue none /dev/mqueue ===== Building kernel ===== * http://devjlanza.wordpress.com/2011/11/14/customize-voyage-linux-image/ * http://wiki.voyage.hk/voyage_kernel.txt * http://kernel-handbook.alioth.debian.org/ch-common-tasks.html * Linux kernel * http://www.linuxchix.org/content/courses/kernel_hacking/lesson3 * Compile single module * http://www.cyberciti.biz/tips/compiling-linux-kernel-module.html * Maybe * https://bbs.archlinux.org/viewtopic.php?id=136812 ==== Requirement (host) ==== apt-get install kernel-package ncurses-dev fakeroot wget bzip2 sharutils ==== Getting Voyage Kernel Source ==== === Method 1: Apt-getting === === Method 2: Download deb source === Download the voyage kernel-source debian package from the following location: http://www.voyage.hk/dists/0.4/linux/ <= stable kernel, voyage-0.4 kernels For example, wget and install the kernel-source package by running "dpkg -i ", something like: wget http://www.voyage.hk/dists/0.4/linux/linux-source-2.6.20-voyage_4.0-2_all.deb dpkg -i linux-source-2.6.20-voyage_4.0-2_all.deb ==== Setting up Kernel Source Tree ==== === Extracting kernel source tarball === By either method, it will install the kernel source tarball to /usr/src. Extract the tarball by: cd /usr/src tar -jxf linux-source-2.6.20-voyage.tar.bz2 This will extract the voyage kernel source to linux-source-2.6.20-voyage === Downloading kernel configuration === Download the corresponding kernel config file from voyage.hk and put to /usr/src: wget http://www.voyage.hk/download/kernel_config/config-2.6.8-486-voyage_2.0-3 cp config-2.6.8-486-voyage_2.0-3 kernel-source-2.6.8-voyage/.config Kernel configuration files can be found [[http://www.voyage.hk/download/kernel_config/|here]]. === Patching kernel === You can now apply your own kernel patch to voyage kernel, here are the commands I use: cd kernel-source-2.6.8-voyage patch -p1 < Look at the output to see if the patch is rejected. (some of the later patches had to be applied with -p4 instead of -p1. ill-diffing?) ==== Building Kernel ==== === Enable kernel module and drivers === Most of the time, you will want to enable some modules compiled for the kernel. If so, run: make menuconfig find the module and enable it. === Edit makefile (optional; see next point) === Edit the makefile to specify the correct version information: EXTRAVERSION = -486-voyage (Not needed if you use --append-to-version!) target architecture (if you're cross-compiling) and compiler version (gcc-3.3 for 2.6.17-486-voyage): ARCH ?= $(SUBARCH) CROSS_COMPILE ?= HOSTCC = gcc-3ve.3 CC = $(CROSS_COMPILE)gcc-3.3 *Note: please add this to Makefile if have compiling problems CFLAGS_KERNEL = -fno-tree-scev-cprop === Building Debian kernel image === To build debian kernel image: make-kpkg --revision="2.0-3Custom" --append-to-version "-486-voyage" kernel-image --rootcmd fakeroot --initrd This is the command that will build the voyage kernel. You may want to modify the --revision and --append-to-version flags to specify the different revision and version of your choice. Read the output to see if the compilation fails. If no error spotted, the new debian kernel package can be found in /usr/src/. The kernel image should be named like kernel-image-2.6.8-486-voyage-2.0.3Custom_i386.deb. In some cases, if you have some compile problem, you could do a 'make' in the root of kernel-source and then do a debian style make-kpkg: fakeroot make-kpkg --append_to_version -486-voyage --revision=3.0-2Cust kernel_image --initrd this way has worked for me.. Remember to upgrade grub after the installation of the new kernel: update-grub Optimized commands: #make menuconfig CONCURRENCY_LEVEL=3 make-kpkg --revision="3.0newconf" --append-to-version "-jlanza-voyage" --initrd kernel-image You can change the revision and version strings to what ever you want. If you are cross-compiling from a 64 bits machine to generate a 32 bits image, you should be aware of setting the proper options to gcc to work (-m32). CONCURRENCY_LEVEL=3 DEB_HOST_ARCH=i386 ARCH=i386 make-kpkg --arch i386 --cross-compile - --revision="3.0usb" --append-to-version "-486-voyage" --initrd kernel-imag === Building Debian kernel source === You might also want to build kernel source so that other people can further enhance the updated kernel. make-kpkg --revision="2.0-3Custom" --append_to_version "-486-voyage" kernel-source --rootcmd fakeroot Typically, this was usually run before building kernel image ==== Install debian kernel image ==== Copy the debian kernel package to voyage and install the kernel by running "dpkg -i". You will need to answer a couple of questions to complete the installation of the kernel image. After all, reboot the voyage linux to make it effective! Update grub update-grub reboot ===== Grub2 boot order ===== That's it for now. You have the tools you need to start working. Still, to make things clearer, I've prepared a short summary that concludes the introduction and basic usage sections. Here we go: GRUB 2 has three main parts: /etc/default/grub - the file containing GRUB 2 menu settings. /etc/grub.d/ - the directory containing GRUB 2 menu creating scripts. /boot/grub/grub.cfg - the GRUB 2 configuration file, not editable. update-grub command reads the /etc/grub.d directory and looks for executable scripts inside it. The scripts are read, in the order of their numbering, and written into the grub.cfg file, along with the menu settings read from the /etc/default/grub file. Boot entries come from several sources - the default that comes with the distribution, other operating systems probed on the connected disks and custom scripts written by the user, following a strict syntax. The scripts are written as shell (sh). You can add/remove entries by simply chmod-ing the scripts; no need to delete them. GRUB 2 can be reinstalled anytime you want, even while booted in the OS. Good so far? Excellent. You see, it's rather simple. Now, let's see a few real-life cases. Afterwards, we will customize GRUB 2 and learn how to recover from serious errors and misconfigurations. ===== Setup system ===== Software Packages: vi /etc/apt/sources.list replace jp with de! apt-get update Hostname: vi /etc/hostname imavoyage-alix root: voyage APT: apt-get install avahi-{autoipd,daemon,discover,utils} apt-get install build-essential autotools-dev cdbs check checkinstall dctrl-tools automake libtool libc6-dev subversion pkg-config strace gdb apt-get install vim-nox tree apt-get install locales ETCs: apt-get install libusb-{1.0-0-dev,1.0-0,libusb-dev} ===== compile software ===== Problem: perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LC_CTYPE = "UTF-8", LANG = "en_US.UTF-8" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). locale: Cannot set LC_CTYPE to default locale: No such file or directory locale: Cannot set LC_ALL to default locale: No such file or directory vim /etc/environment # add this line LC_ALL="en_US.utf8" OR dpkg-reconfigure locales ==== Lib paths ==== vim /etc/ld.so.conf.d/usr_local_lib.conf /usr/local/lib ldconfig