WSL 的BASHRC 設定紀錄

這是目前有效的設定紀錄

# .bashrc
#ssh for wsl
sudo service ssh start
#docker alias
alias dockerstop=’docker stop $(docker ps -a -q)’
alias dockerclean=’docker rm $(docker ps -a -q)’
alias dockerrmi=’docker rmi $(docker images -q)’

#alias other

alias ll=’ls -al’
# get current branch in git repo
function parse_git_branch() {
BRANCH=`git branch 2> /dev/null | sed -e ‘/^[^*]/d’ -e ‘s/* \(.*\)/\1/’`
if [ ! “${BRANCH}” == “” ]
then
STAT=`parse_git_dirty`
echo “[${BRANCH}${STAT}]”
else
echo “”
fi
}

export LS_OPTIONS=’–color=auto’
#eval “$(dircolors -b)”
alias ls=’ls $LS_OPTIONS’
#LS_COLORS=$LS_COLORS:’di=0;35:’ ; export LS_COLORS
#eval “$(dircolor -b)”
#alias ls =’ls $LS_COLORS’;
# get current status of git repo
function parse_git_dirty {
status=`git status 2>&1 | tee`
dirty=`echo -n “${status}” 2> /dev/null | grep “modified:” &> /dev/null; echo “$?”`
untracked=`echo -n “${status}” 2> /dev/null | grep “Untracked files” &> /dev/null; echo “$?”`
ahead=`echo -n “${status}” 2> /dev/null | grep “Your branch is ahead of” &> /dev/null; echo “$?”`
newfile=`echo -n “${status}” 2> /dev/null | grep “new file:” &> /dev/null; echo “$?”`
renamed=`echo -n “${status}” 2> /dev/null | grep “renamed:” &> /dev/null; echo “$?”`
deleted=`echo -n “${status}” 2> /dev/null | grep “deleted:” &> /dev/null; echo “$?”`
bits=”
if [ “${renamed}” == “0” ]; then
bits=”>${bits}”
fi
if [ “${ahead}” == “0” ]; then
bits=”*${bits}”
fi
if [ “${newfile}” == “0” ]; then
bits=”+${bits}”
fi
if [ “${untracked}” == “0” ]; then
bits=”?${bits}”
fi
if [ “${deleted}” == “0” ]; then
bits=”x${bits}”
fi
if [ “${dirty}” == “0” ]; then
bits=”!${bits}”
fi
if [ ! “${bits}” == “” ]; then
echo ” ${bits}”
else
echo “”
fi
}

export PS1=”[\[\e[36m\]\u\[\e[m\]@\[\e[33m\]\h\[\e[m\]:\[\e[1;31m\]\w\[\e[m\]]\e[1;32m\][\t\[\e[m\]]\[\e[31m\]\`parse_git_branch\`\[\e[m\]$ “

# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

How to add Respond Json function in OPENX Without plugin

1.add folder in {documnet_root}/www/{yourname}/

ex. adserver/json/

2.add php file ex.api.php

3.add content like this


//xid param from your url like {yourdoamin}/www/json/api.php?xid=10
//xid eq zoneid
//set your AD like banner type


$_GET['zoneid'] =$_GET['xid'];




// Require the initialisation file
require_once '../../init-delivery.php';

// Required files
require_once MAX_PATH . '/lib/max/Delivery/adSelect.php';
require_once MAX_PATH . '/lib/max/Delivery/flash.php';

// No Caching
MAX_commonSetNoCacheHeaders();

//Register any script specific input variables
MAX_commonRegisterGlobalsArray(array('refresh', 'resize', 'rewrite', 'n'));

// Initialise any afr.php specific variables
if (!isset($rewrite))   $rewrite = 1;
if (!isset($refresh))   $refresh = 0;
if (!isset($resize))    $resize = 0;
 
// Get the banner

$banner = MAX_adSelect($what, $campaignid, $target, $source, $withtext, $charset, $context, true, $ct0, $loc, $referer);
// Send cookie if needed
if (!empty($n)) {
    if (!empty($banner['html'])) {
        // Send bannerid headers
        $cookie = array();
        $cookie[$conf['var']['adId']] = $banner['bannerid'];
        // Send zoneid headers
        if ($zoneid != 0) {
            $cookie[$conf['var']['zoneId']] = $zoneid;
        }
        // Send source headers
        if (!empty($source)) {
            $cookie[$conf['var']['channel']] = $source;
        }
        // Set the cookie
        MAX_cookieAdd($conf['var']['vars'] . "[$n]", json_encode($cookie, JSON_UNESCAPED_SLASHES));
    } else {
        MAX_cookieUnset($conf['var']['vars'] . "[$n]");
    }
}

MAX_cookieFlush();

MAX_commonSendContentTypeHeader('text/html', $charset);

// Rewrite targets in HTML code to make sure they are
// local to the parent and not local to the iframe
if (isset($rewrite) && $rewrite == 1) {
    $banner['html'] = preg_replace('#target\s*=\s*([\'"])_parent\1#i', "target='_top'", $banner['html']);
    $banner['html'] = preg_replace('#target\s*=\s*([\'"])_self\1#i', "target='_parent'", $banner['html']);
}

// Build HTML
$outputHtml = "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>\n";
$outputHtml .= "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n";
$outputHtml .= "<head>\n";
$outputHtml .= "<title>".(!empty($banner['alt']) ? $banner['alt'] : 'Advertisement')."</title>\n";

// Include the FlashObject script if required
if (isset($banner['contenttype']) && $banner['contenttype'] == 'swf') {
    $outputHtml .= MAX_flashGetFlashObjectExternal();
}

// Add refresh meta tag if $refresh is set and numeric
if (isset($refresh) && is_numeric($refresh) && $refresh > 0) {
    $dest = MAX_commonGetDeliveryUrl($conf['file']['frame']).'?'.$_SERVER['QUERY_STRING'];
    parse_str($_SERVER['QUERY_STRING'], $qs);
    $dest .= (!array_key_exists('loc', $qs)) ? "&loc=" . urlencode($loc) : '';

    $refresh = (int)$refresh;
    // JS needs to be escaped twice: the setTimeout argument is evaluated at runtime
    $jsDest = addcslashes(addcslashes($dest, "\0..\37\"\\"), "'\\");
    $htmlDest = htmlspecialchars($dest, ENT_QUOTES);

    // Try to use JS location.replace since browsers deal with this and history much better than meta-refresh
    $outputHtml .= "
    <script type='text/javascript'><!--// <![CDATA[
        setTimeout('window.location.replace(\"{$jsDest}\")', " . ($refresh * 1000) . ");
    // ]]> --></script><noscript><meta http-equiv='refresh' content='".$refresh.";url={$htmlDest}'></noscript>
    ";
}

if (isset($resize) && $resize == 1) {
    // If no banner found, use 0 as width and height
    $bannerWidth = empty($banner['width']) ? 0 : $banner['width'];
    $bannerHeight = empty($banner['height']) ? 0 : $banner['height'];

    $outputHtml .= "<script type='text/javascript'>\n";
    $outputHtml .= "<!--// <![CDATA[ \n";
    $outputHtml .= "\tfunction MAX_adjustframe(frame) {\n";
    $outputHtml .= "\t\tif (document.all) {\n";
    $outputHtml .= "\t\t\tparent.document.all[frame.name].width = ".$bannerWidth.";\n";
    $outputHtml .= "\t\t\tparent.document.all[frame.name].height = ".$bannerHeight.";\n";
    $outputHtml .= "\t\t}\n";
    $outputHtml .= "\t\telse if (document.getElementById) {\n";
    $outputHtml .= "\t\t\tparent.document.getElementById(frame.name).width = ".$bannerWidth.";\n";
    $outputHtml .= "\t\t\tparent.document.getElementById(frame.name).height = ".$bannerHeight.";\n";
    $outputHtml .= "\t\t}\n";
    $outputHtml .= "\t}\n";
    $outputHtml .= "// ]]> -->\n";
    $outputHtml .= "</script>\n";
}

$outputHtml .= "<style type='text/css'>\n";
$outputHtml .= "body {margin:0; height:100%; background-color:transparent; width:100%; text-align:center;}\n";
$outputHtml .= "</style>\n";
$outputHtml .= "</head>\n";

$jsonArr['html'] =  ($banner['html']);

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials true');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept,token,Access-Token');
header('Access-Control-Max-Age: 1728000');
header("Content-type: application/json; charset=utf-8");

echo json_encode($jsonArr);
exit;

Laravel 5/7 Redis的分庫設定

在此之前,有一些預備工作要做的

Redis driver

按照官方建議 用phpredis

redis是可以設定他在他一個db內的,例如我的全站設定檔是在db3,我的客戶暫存是在db1,預設是在db0

當我在連線設定沒有指定,預設會跑到db0,那為什麼要分呢?因為redis是沒有辦法做特徵全部刪除的,例如他無法做到刪除key name 為abc_開頭的資料 ,我必須要知道keyname的完整名稱,這樣如果我的網站站存檔要全部更新的話,就很麻煩,你可能還要跑資料庫迴圈把相關資料叫出來,不能爽快的flushdb…,但如果你今天把資料分門別類,那你就可以對db3下達flush指令,這樣效率會高一點,而且你要改小部分資料的時候,在沒有看code的情況下,透過工具也比較好找,例如我只要改一個設定檔案,我只要透過Medis之類的GUI工具就可以修改,不需要半夜打電話叫工程師起床尿尿 叫他看一下他設定的key name是什麼

在config/database.php 內 記錄了redis的設定


'redis' => [

        'client' => env('REDIS_CLIENT', 'phpredis'),

        'options' => [
            'cluster' => env('REDIS_CLUSTER', 'redis'),
            'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
        ],

        'default' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => env('REDIS_DB', '0'),
        ],
        'db1' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' =>'1',
        ],
        'db2' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' =>'2',
        ],
        'db3' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' =>'3',
        ],
        'cache' => [
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => env('REDIS_CACHE_DB', '1'),
        ],

    ],
這裡的陣列中,我設定了幾個索引名稱,這個在後來的連線上會用到

設定連線




        $setobj = Redis::connection('db3');

        $rf=[];
        if($setobj->exists($key)){
            $rf['exist']=1;
            $rf['rs']=$setobj->get($key);

        }else{
            $rf['exist']=0;

        }

對應到上面的索引設定,我就是從db3裡面撈取資料,而不是從預設的db0撈取,這樣不同的程式甚至是不同的功能,就可以共用同一個redis,而不會互相影響到

PHP JENKINS 設定紀錄

原始碼管理

Repository URL

這裡是填入Repository URL 的地方 這裡的設定用http

Credentials

因為用的是http,所以輸入git 帳號密碼

Branches to build

*/master

如果是別的branch 就寫branch名稱 當然 這個branch是在線上的 不是你本地端的

建置環境

Delete workspace before build starts

建置bash

#遠端主機 ,你可以設定多個 這個是單主機設定
HOST="{your_host_ip}"
#多主機 中間空白
HOST="{ip1} {ip2} {ip3}" 

#PHP 安裝 composer
#主機要先裝好composer
COMPOSER=/usr/local/sbin/composer
COMPOSERINSTALL=".composer.sh"

#遠端主機 的HTM資料來 設定擁有者 這裡設計上是讓nginx掌管php目錄
HTM=/var/html/blog
HTMOWNER="nginx:nginx"
 

#遠端主機 的 SSH 登入設定
RUSER="{user}"

# SSH 連線參數
#登入遠端主機要用的key,這裡的位址是指jenkins的位置
OPT="-i ~/.ssh/key.pem"
OPT="$OPT -o StrictHostKeyChecking=no"
OPT="$OPT -o UserKnownHostsFile=/dev/null"
OPT="$OPT -o LogLevel=ERROR"
OPT="$OPT -o ConnectTimeout=20"

SCP="scp $OPT -r -p "

SRC=$WORKSPACE

FAILHOST=""
FAILTOTAL=0
TOTAL=0
for IP in $HOST
do
    TOTAL=$((TOTAL+1))
done

IPSEQ=0
# 上傳到 遠端主機
for IP in $HOST
  
do
	IPSEQ=$(($IPSEQ+1))
    echo "Update Server : $IP ($IPSEQ/$TOTAL/$FAILTOTAL)"
	SSH="ssh $OPT $RUSER@$IP "
	SCP="scp $OPT -r -p "
    RSYNC="rsync -a"
    # 測試連線
    if ! $SSH /bin/true; then
        echo "Update Fail $IP"
        FAILHOST="$FAILHOST $IP"
        FAILTOTAL=$((FAILTOTAL+1))
        continue 
    fi
    
    # 先建資料夾
    $SSH sudo mkdir -p $HTM
    sleep 1
	# 複製 HTM
    $RSYNC --chown=$HTMOWNER -e "ssh $OPT" $SRC/ $RUSER@$IP:$HTM/
    sleep 1
    # 更換設定檔
   #把正式的.env檔設定上去 這裡設定檔叫做.prod
    $RSYNC --chown=$HTMOWNER -e "ssh $OPT" $SRC/.prod $RUSER@$IP:$HTM/.env
    # 檢查 composer 安裝
    $SSH sudo sh $HTM/$COMPOSERINSTALL $HTM
    # 用 composer 安裝
    $SSH sudo $COMPOSER i -d $HTM
    #LARAVEL  清緩存 三指令
    CMD="cd $HTM;
    php artisan cache:clear;
    php artisan config:clear;
    php artisan route:clear;
    "
    $SSH $CMD
done

if [ ! -z "$FAILHOST" ];then
    echo "FAIL IP TOTAL $FAILTOTAL / $TOTAL"
	echo $FAILHOST
    /bin/false
fi

CVE-2015-0235 安全性更新

這是個老bug..如果有更新過應該沒問題
Redhat已經放在repo內了,yum已經支援了

yum update –cve CVE-2015-0235
即可
打這段沒用的人
請先安裝 yum-security plugin

centos 6
yum install yum-plugin-security
centos 5
yum install yum-security

檢查結果

# rpm -q –changelog glibc | grep CVE-2015-0235
會出現
– Fix parsing of numeric hosts in gethostbyname_r (CVE-2015-0235, #1183532)

mysql扣庫存的動作

今天研究一個主題,扣庫存,看到一個關鍵詞組
“select for update mysql”
看了幾個人的寫法
整合起來就是這樣

table : tb1
欄位
id
stock

扣庫存

BEGIN;
select stock from tb1 where id=1 for update;
update tb1 set stock = stock -2 where id =1 and stock >=2;
commit;
故意用2…為了是顯示要扣庫存的條件,這裡的條件是扣兩件所以where stock>=2才能跑stock -2
使用transation時 測試的結果
開兩個視窗
conn a
conn b

conn a執行
BEGIN;
select stock from tb1 where id=1 for update;
update tb1 set stock = stock -1 where id =1 and stock >=1;

再來
conn b執行
update tb1 set stock = stock -1 where id =1 and stock >=1;

這時候conn b會等到conn a comit之後才會扣庫存
conn a 執行commit;
transcation結束
換執行 conn b
如果庫存被扣完 那就會更新失敗傳回0

現在的問題是
扣庫存要用哪一種語法呢?

stock = stock -1
還是
sotck = $a

前者看起來比較沒有庫存錯誤的問題,但必須配合transaction使用
至於$a的值也是從select來的,可能會有時間差的問題
mysql 官網在介紹for update這件事情的時候,是用stock = stock -1當範例的,終究這是最後的值,沒有經過select的時間差

最後這只有innodb才做的了….

windows7 修改hosts檔案無效

怎麼改都沒用,非常怪
先檢查有沒有使用小紅傘,有的話把即時保關閉即可
其他防毒也是同樣的道理
但如果還是沒用呢???

1.把hosts檔案從etc裡面複製出來
2.把剛剛複製出來的檔案再覆蓋上去
這時候如果沒有出現UAC的保護叫你按確認
代表這個檔案已經故障了……………

解決方案
1.複製任何在etc內的檔案一個,放到桌面上
copy any file in C:\Windows\System32\drivers\etc to desktop
2.修改名字叫hosts
edit file name to hosts
3.修改內容成為一個正常的hosts
edit hosts
4.覆蓋回去,這時候看UAC的反應,如果有,那就會生效了
copy file to C:\Windows\System32\drivers\etc , if show UAC alert…it work!!
我猜測原因,或許是這個檔案要在某些windows7的權限下才有效果…
此篇紀錄下來