2015年12月9日 星期三

ADB in Linux: cannot bind 'tcp:5037'

Problem: 
   ./adb start-server
   * daemon not running. starting it now on port 5037 *
   cannot bind 'tcp:5037'
   ADB server didn't ACK
   * failed to start daemon *
 
Solution #1:
   Kill processes using port 5037
      netstat -ap|grep "5037"
      kill -p 
 
Solution #2:
   strace ./adb start-server
   ...
   socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
   connect(3, {sa_family=AF_INET, sin_port=htons(5037),
   sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ETIMEDOUT (Connection timed out) 
   ==> ifconfig lo up
 
 

2015年11月26日 星期四

How to debug makefile ?

1. info, error

SOME_VARIABLE := $(SOME_OTHER_VARIABLE)/$(ANOTHER_VARIABLE)
$(info SOME_VARIABLE = $(SOME_VARIABLE)) -> 相當於 echo $(error SOME_VARIABLE = $(SOME_VARIABLE)) -> echo + exit

2. make -n -p

可以把所有的 target 展開,方便追找不到的 rule

How to find only text files?

find . -type f -exec grep -Iq . {} \; -and -print
find . -type f -print0 | xargs -0 grep -I "needle text"

2015年11月25日 星期三

GIT handbook

--------------------------------------------------------------------------------------------------------------------
GIT DIFF
--------------------------------------------------------------------------------------------------------------------
List the file names only that changed between two commits:
$ git diff --name-only [commit1] [commit2] [file3]

List the file names (and some more detail) that changed between two commits:
$ git diff --stat svr/bl2 svr/bl3
$ git diff --name-status [SHA1 [SHA2]]
Show diff using graphics GUI:
$ git difftool -t meld  [commit1] [commit2] [file3]

git diff [-- folder/file] => workspace vs staged
git diff HEAD => workspace vs HEAD
git diff --cached [HEAD] => staged vs HEAD
git diff HEAD^ HEAD => HEAD^ vs HEAD

--------------------------------------------------------------------------------------------------------------------
GIT  all
--------------------------------------------------------------------------------------------------------------------
Remove local untracked files from workspace:
$ git clean -f -d -n         # -d to include folders;  -n for dry run
$ git clean -f -d -x         # -x to ignore .gitignore

List all branches/tag:
$ git branch -a
$ git tag
$ git ls-remote --tags
List all tags and their SHA:
$ git show-ref --tag

Remove a local branch:
$ git branch -d
$ git branch -D

Remove a local tag:
$ git tag -d <tag>


Remove a remote branch/tag:
$ git push :<branch/tag>

Fetch a repository from a remote (update database only):
$ git fetch --prune

Multiple remotes, pushed (and fetched) independently:$ cd myproject
$ git remote add bitbucket ssh://git@bitbucket.org/user/myproject.git
$ git push bitbucket master
Single remote with multiple URLs, pushed (and fetched) consecutively.
$ cd myproject
$ git remote set-url --add origin ssh://git@bitbucket.org/user/myproject.git 
$ git push origin master

Revoke recent 2 commits:
git reset HEAD~2

List SHA and comment, one line per one commit, from bl2 to bl3:
$ git log --pretty=oneline --author=flxm.com svr/bl2..svr/bl3

Replay the the patches, from the common ancestor of the bl2 and dev branches, onto dev2:
$ git rebase --onto dev2 svr/bl2 svr/dev1

Display history:
$ gitk --all --select-commit=svrX/branchY

Change commit author at one specific commit
For example, if your commit history is A-B-C-D-E-F with F as HEAD, and you want to change the author of C and D, then you would...
  1. Specify git rebase -i B
  2. change the lines for both C and D to edit
  3. Once the rebase started, it would first pause at C
  4. You would git commit --amend --author="Author Name "
  5. Then git rebase --continue
  6. It would pause again at D
  7. Then you would git commit --amend --author="Author Name " again
  8. git rebase --continue
  9. The rebase would complete.

List all authors
$ git log --format='%aN <%aE>'
$ git log --format='%aN>' | sort -u
List everyone who committed to a particular project, listed alphabetically. To list by commits, add -n to the shortlog.
$ git shortlog -s | cut -c8-
Gets the authors, sorts by number of commits (as a vague way of estimating how much of the project is their work, i.e. the higher in the list, the more they've done) and then outputs the results.
$ git log --format='%aN <%aE>' | awk '{arr[$0]++} END{for (i in arr){print arr[i], i;}}' | sort -rn | cut -d\  -f2-

Cherry-pick only changes to certain files
git cherry-pick -n 

# unstage modifications you don't want to keep, and remove the
# modifications from the work tree as well.
# this does work recursively!
git checkout HEAD 

# commit; the message will have been stored for you by cherry-pick
git commit
If the vast majority of modifications are things you don't want, instead of checking out individual paths (the middle step), you could reset everything back, then add in what you want:
# unstage everything
git reset HEAD

# stage the modifications you do want
git add 

# make the work tree match the index
# (do this from the top level of the repo)
git checkout .
Q: .gitignore doesn't work
A1: for every line, remove all invisible tailing characters, including SPACE; CR,LF,NULL are OK.
A2: use below commands.  If history was pushed to remotes, rework is needed to clean remote history.
git rm -r --cached .
git add .
git commit -m "fixed untracked files"
Q: List commits w/ logs containing a keyword.
A: git log --grep="keyword"

Q: fast forward to branch head
A: git merge /.

Q: find possible filenames in commits
A: git log --name-only | grep

Q: list commits modify a file
A: git log --follow --

Q: show SHA of the commit before a specific commit
A: git log ^1

Q: show SHA of all commits on a specific branch
A: git log --pretty=format:'%H'

Q: check if a given commit on a specific branch
A: git log --pretty=format:'%H' | grep

Q: show history for a sub directory
A: git log --

Q: show commit ID of tags/branches
A: git show-ref

Q: show commit ID of current commit
A: git log --pretty=format:'%h' -n 1

Q: list tags points to given commit ID
A: git tag --points-at

Q: list tags points to current commit
A: git tag --points-at `git log --pretty=format:'%h' -n 1`

Q: List all files currently under source control of a specific branch.
A: git ls-tree -r --name-only

Q: List of all files that ever existed
A: git log --pretty=format: --name-status | cut -f2- | sort -u

Q: checkout certain revision of a file under a new name
A: git show HEAD^:main.cpp > old_main.cpp

Q: Resolve Git merge conflicts in favor of their changes during a pull
A: git merge --strategy-option theirs

Q: How to checkout src/main.c to another filename?
A: git show HEAD~4:src/main.c > main.c.prev4

Q: How to view the change history of a file?
A: git log -- [filename]
    gitk --follow [filename]

Q: How to see remote tags?
A: git ls-remote --tags <remote>

Q: How to list branches that contain a given commit?
A: git branch --contains <commit>

Q: How to archive all files modified ?
A: git archive -o update.zip <dst_commit> $(git diff --name-only <src_commit> <dst_commit>)

Q: How to show stashes in gitk without `--all` option?
A: gitk `git stash list --format=%H` &

Q: How to show current branch?
A: git branch | grep '*'

--------------------------------------------------------------------------------------------------------------------
GIT patch create & apply
--------------------------------------------------------------------------------------------------------------------
  • git format-patch --root
    • 從root到指定commit的patch
  • git format-patch -n
    • 起, 最近n個commit的patch
  • git format-patch 5e86795..f2b286a
    • 從指定起始commit到結束commit的patch
-o 可以設定輸出的資料夾
git am 0001-modify-page.patch


--------------------------------------------------------------------------------------------------------------------
GIT configuration
--------------------------------------------------------------------------------------------------------------------
git config --global commit.template $HOME/.gitmessage.txt
git config receive.denyDeleteCurrent false

--------------------------------------------------------------------------------------------------------------------
REPO
--------------------------------------------------------------------------------------------------------------------
Add remote for all repositories listed in the manifest.xml.
$ repo forall -c "git remote add ssh://@/home//\$REPO_PROJECT"

List tags points to current commit for all repositories
$ repo forall -c "pwd; git tag --points-at \`git log --pretty=format:'%h' -n 1\`"

Apply manifest to another work space
yulin@WNC:/HOUSE/yulin/mdm9607-le-2-1_amss_standard_oem_r00040p1_PostCS/apps_proc$ repo forall -c "cd /HOUSE/yulin/ptr9628/apps_proc/\$REPO_PATH; pwd; git tag LE201r00075.1 \$REPO_RREV"

--------------------------------------------------------------------------------------------------------------------
Account
--------------------------------------------------------------------------------------------------------------------

  • ssh-keygen -t rsa 或 ssh-keygen -d (dsa) => 產生出 id_rsa, id_rsa.pub
  • scp id_rsa.pub server_hostname:~/.ssh/
  • ssh server_hostname
  • cat .ssh/id_rsa.pub >> .ssh/authorized_keys 即可
  • 這樣子就可以 key 認證登入, 不需輸入密碼

--------------------------------------------------------------------------------------------------------------------
'git log' and 'git show-ref' show different SHA1
--------------------------------------------------------------------------------------------------------------------
~/9150w$ git show-ref --deref v00.07.2k.00
2c79b9c8211db8df33b3e3e387a41edd8a391b72 refs/tags/v00.07.2k.00
b1895be23436bd74642bbd7cc9b0177e70177848 refs/tags/v00.07.2k.00^{}

~/9150w$ git show-ref v00.07.2k.00
2c79b9c8211db8df33b3e3e387a41edd8a391b72 refs/tags/v00.07.2k.00

~/9150w$ git log -n 1  v00.07.2k.00 | grep commit
commit b1895be23436bd74642bbd7cc9b0177e70177848

Refer to https://stackoverflow.com/questions/2534773/what-is-dereference-in-the-context-of-git-show-ref-d,
command "git tag <tag> <branch or HEAD or alike>" is suspected to create an annotated tag.
command "git tag <tag>" creates a lightweight tag.



# Show commits that contains the code, then you can: git show <commit_sha>
git log -S "whatever you want to search for"

# An even easier way to show matches right there on the spot
git log -S "your search term" -p

# Same as above, except applied to all branches instead of the checked out branch
git log -S "something" -p --all

# Limit your search to only specific files in a specific directory
git log -S "something specific" -p -- **/models/user*.py

# Search for a regex instead of a string (note the -G instead of -S)
git log -G '^alias \w+=".*"$' -p

# a string or regular expression with the same flag
git log --grep "your search term"

# Same as above, except applied to all branches instead of the checked out branch
git log --grep "something else" --all


2015年10月14日 星期三

make clean, make mrproper, make distclean

from the Makefile:

###
# Cleaning is done on three levels.
# make clean          Delete most generated files;
#                              Leave enough to build external modules
#                              (remove all the object *.o and kernel object files *.ko
#                               and a few other things)
# make mrproper   Delete the current configuration, and all generated files
# make distclean     Remove editor backup files, patch leftover files and the like
#                               (plus remove your config file, the dependency files,
#                                and everything else that make config creates.)

2015年9月27日 星期日

[Linux][Driver][I2C] 在device tree的架構下, i2c device與driver如何對應?


在device tree的架構下, i2c device 與 driver 是如何 match
原文: http://janbarry0914.blogspot.tw/2014/08/device-tree-i2c-device-driver-match.html

[文章重點]
了解在 device tree 的架構一下, i2c device 與 i2c driver 是如何 match 進而 call 到 driver 裡的 probe function (本文章是以 Qualcomm MSM8974 liquid board 為例)

[文章目錄]
  1. 在 device tree 架構下的作法
  2. device 如何被註冊
  3. driver 如何與 device 匹配

[在 device tree 架構下的作法]
Linux kernel driver 的架構都是由匯流排 ( bus ), 裝置 ( device ) 和 驅動程式 ( driver ) 所構成, 匯流排將裝置和驅動程式綁定. 當 Linux kernel 在註冊一個裝置的時候, 會尋找與之匹配的驅動程式; 相反的, 當 Linux  kernel 在註冊一個驅動程式的時候, 也會尋找與之匹配的裝置, 而匹配這動作是由匯流排負責完成.  然而 device tree 在做匹配綁定的概念跟之前的作法仍是一致的, 換句話說, 還是利用字串的比對, 只是由原本的 name 屬性改由 device tree 內的 compatible 屬性去做而已.


首先會說明裝置是如何被建立, 是如何被加到匯流排中, 接下來會說明驅動程式在註冊後, 匯流排如何去做這匹配的動作.

[device 如何被註冊]
那裝置是如何被加到匯流排中?  那就是透過 of_platform_populate( ) 這 function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
 * of_platform_populate() - Populate platform_devices from device tree data
 * @root: parent of the first level to probe or NULL for the root of the tree
 * @matches: match table, NULL to use the default
 * @parent: parent to hook devices from, NULL for toplevel
 *
 * Similar to of_platform_bus_probe(), this function walks the device tree
 * and creates devices from nodes.  It differs in that it follows the modern
 * convention of requiring all device nodes to have a 'compatible' property,
 * and it is suitable for creating devices which are children of the root
 * node (of_platform_bus_probe will only create children of the root which
 * are selected by the @matches argument).
 *
 * New board support should be using this function instead of
 * of_platform_bus_probe().
 *
 * Returns 0 on success, < 0 on failure.
 */
int of_platform_populate(struct device_node *root,
   const struct of_device_id *matches,
   const struct of_dev_auxdata *lookup,
   struct device *parent)
{
 struct device_node *child;
 int rc = 0;

 root = root ? of_node_get(root) : of_find_node_by_path("/");
 if (!root)
  return -EINVAL;

 for_each_child_of_node(root, child) {
  rc = of_platform_bus_create(child, matches, lookup, parent, true);
  if (rc)
   break;
 }

 of_node_put(root);
 return rc;
}

從這 function 的註釋中了解到它會走遍整個 device tree 並為 每一個 device node 去創建 device. 接下透過 call flow來了解先後關係.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
DT_MACHINE_START(MSM8974_DT, "Qualcomm MSM 8974 (Flattened Device Tree)")
 .map_io = msm8974_map_io,
 .init_irq = msm_dt_init_irq,
 .init_machine = msm8974_init,
 .handle_irq = gic_handle_irq,
 .timer = &msm_dt_timer,
 .dt_compat = msm8974_dt_match,
 .reserve = msm_8974_reserve,
 .init_very_early = msm8974_init_very_early,
 .restart = msm_restart,
 .smp = &msm8974_smp_ops,
MACHINE_END

 msm8974_init( ) @ board-8974.c 
 |--> board_dt_populate( ) @ board-dt.c 
     |--> of_platform_populate( )  @ platform.c
        |--> of_plateform_bus_create( ) @ platform.c 
            |--> of_platform_device_create_pdata( ) @ platform.c 
               |--> of_device_alloc( ) @ platform.c
                   /*除了分配struct platform_device的記憶體,
                     還分配了該platform device需要的resource的記憶體*/  
               |--> of_device_add( ) @ device.c /*把這個platform device加入系統中*/  
                   |--> device_add( )  /* 它會call device_create_file( ) 
                                       在 sysfs中建立 attribute file for the device*/

[driver 如何與 device 匹配]
在看完 " device tree 如何新增 device 到系統中" 後, 接下來看 device driver 的註冊過程, 在此, 以 i2c device driver  - audio codec rt5627 為例.

 i2c_add_driver( ) @ i2c.h  
 |-> i2c_register_driver( ) @ i2c-core.c /*將 device_driver中的 bus_type 設成 i2c_bus_type */  
    |--> driver_register( ) @ driver.c  
        |--> bus_add_driver( ) @ bus.c /* 建立 sysfs file node 與 attr*/  
           |--> driver_attach( ) @ dd.c  
              |--> bus_for_each_dev( drv->bus, NULL, drv, __driver_attach) @ bus.c  
                  |--> __driver_attach @ dd.c  
                      |--> driver_match_device(drv, dev) @base.h  
                           |--> i2c_device_match( ) @ i2c-core.c  
                               /***********************************************  
                           如果是device tree, 會透過 of_driver_match_device( ) 去做匹配的動作  
                           如果不是device tree就改用 i2c_match_id( ) 去完成匹配的動作  
                              ***************************************************/  
                  |--> driver_probe_device( ) @ dd.c  
                       /*如果匹配成功, 接下來就要準備 call driver 中的 probe function*/
                       |--> really_probe( ) @ dd.c  
                           |--> i2c_device_probe( ) @ i2c-core.c  
                                |--> rt5627_i2c_probe( ) @ rt5627.c   

從上述的 call flow 得知, device tree 是透過 of_driver_match_device( ) 來做 device 與 driver 匹配的工作. 再從下述的 call flow 得知, 其實最後就是拿 device tree 中的 compatible 屬性跟 driver 中的 of_match_table->compatible 做字串的比較, 如果字串相同, 那就匹配成功囉.

 of_driver_match_device( ) @ of_device.h  
 |--> of_match_device(drv-> of_match_table, dev) @ device.c  
     |--> of_match_node( drv->of_match_table, dev->node) @ base.c  
         |--> of_device_is_compatible(node, drv->of_match_table->compatible) @ base.c 
             |--> of_compat_cmp( ) @ prom.h  
                  /*在 of_compat_cmp( ) 會透過 of_get_property()去取得
                    device tree 中 compatible 對應的值(字串), 
                    再跟 drv->of_match_table->compatible 所指的字串做字串比較*/
                 |--> strncmp( ) /*字串的比較*/  

我們再細看一下 of_match_node( ) 在做什麼事

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * of_match_node - Tell if an device_node has a matching of_match structure
 * @matches: array of of device match structures to search in
 * @node:  the of device structure to match against
 *
 * Low level utility function used by device matching.
 */
const struct of_device_id *of_match_node(const struct of_device_id *matches,
      const struct device_node *node)
{
 if (!matches)
  return NULL;

 while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
  int match = 1;
  if (matches->name[0])
   match &= node->name
    && !strcmp(matches->name, node->name);
  if (matches->type[0])
   match &= node->type
    && !strcmp(matches->type, node->type);
  if (matches->compatible[0])
   match &= of_device_is_compatible(node,
      matches->compatible);
  if (match)
   return matches;
  matches++;
 }
 return NULL;
}
EXPORT_SYMBOL(of_match_node);

就 device tree 而言(大部分 driver 的 of_match_table 裡只有填寫 compatible 屬性, 例如: 在下述 rt5627_match_table  這例子裡, 就是只有填寫 compatible 屬性), 它會跑到 of_device_is_compatible( ) 去檢查是否匹配, 下面是就是 of_device_is_compatible( ) 完整的 source code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/** Checks if the given "compat" string matches one of the strings in
 * the device's "compatible" property
 */
int of_device_is_compatible(const struct device_node *device,
  const char *compat)
{
 const char* cp;
 int cplen, l;

 cp = of_get_property(device, "compatible", &cplen);
 if (cp == NULL)
  return 0;
 while (cplen > 0) {
  if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
   return 1;
  l = strlen(cp) + 1;
  cp += l;
  cplen -= l;
 }

 return 0;
}
EXPORT_SYMBOL(of_device_is_compatible);

貼一下關於 of_match_table 是如何放在 driver 中 (以 audio codec rt5627為例)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#ifdef CONFIG_OF
static struct of_device_id rt5627_match_table[] = {
        { .compatible = "realtek,rt5627",},
        { },
};
#else
#define rt5627_match_table NULL
#endif

static struct i2c_driver rt5627_i2c_driver = {
 .driver = {
  .name = "rt5627",
  .owner = THIS_MODULE,
  .of_match_table = of_match_ptr(rt5627_match_table),
 },
 .probe =    rt5627_i2c_probe,
 .remove =   rt5627_i2c_remove,
 .id_table = rt5627_i2c_id,
};

看一下 device tree ( msm8974-liquid.dtsi ) 內, 我們新增一個 i2c device - rt5627 

 &soc {  
    ..  
     i2c@f9923000 {  
           realtek_rt5627@18 {  
                compatible = "realtek,rt5627";  
                reg = <0x18>;  
           };  
      };  
    ...  
 };  

我們將 Realtek rt5627 這顆 audio DAC ( 其 i2c address 是 0x18 ) 掛在 i2c bus 上 ( 其 physical address 為 0xf9923000 的 i2c bus 上).

[結論] 
在使用 device tree 時, 其匹配是利用 device tree 中 的 compatible 屬性, 跟 driver 中的 of_match_tabl e-> compatible 所指的字串做比較, 所以兩個字串要相同, 這樣才會匹配成功.

 [補充]
   針對 rt5627 這 i2c device 是如何被加進系統中做一個補充, 其實在device tree 章節中就有說明 device 是如何被加到系統中 ( board_dt_populate() ->  of_platform_populate( ) -> .... -> device_add( )), 但那只是針對一些父節點而言. 此例中, i2c@f9923000 是父節點, 而 realtek_rt5627@18 是子節點, 那子節點是何時被加到系統中? 在Qualcomm msm8974 平台上, 是在 i2c driver 的 probe function 中去實現, 所以是父節點做完 device <--> driver 的匹配動作之後, 在父節點的 driver 中的 probe function 裡再去找 device tree 中是否還有子節點, 如果有, 就開始一連串 device 註冊的動作.

 qup_i2c_probe( ) @ i2c-qup.c  
 |--> i2c_add_numbered_adapter( ) @ i2c-core.c   
     /* 宣告 i2c adapter 並給予 bus number*/  
 |--> of_i2c_register_device( ) @ of_i2c.c  
     /*走遍 child nodes, 並為 child nodes 註冊 device nodes*/  
     |--> i2c_new_device( ) @ i2c-core.c   
         /*為這 i2c device 依bus number 與 address命名, 例如: 4-0018  
          表示該 device 位於 bus 4, i2c address 是 0018*/  
        |--> device_register( ) @ core.c  
            |--> device_add ( ) @ core.c  

[Linux][USB] How to mount a USB flash disk ?


If you are not sure what device your system is using, type:
tail -f /var/log/messages

Now insert the usb device.
You should see similar output appear on your console:
Initializing USB Mass Storage driver...
usb.c: registered new driver usb-storage
scsi3 : SCSI emulation for USB Mass Storage devices
Vendor: Generic Model: STORAGE DEVICE Rev: 1.02
Type: Direct-Access ANSI SCSI revision: 02
Attached scsi removable disk sda at scsi3, channel 0, id 0, lun 0
SCSI device sda: 512000 512-byte hdwr sectors (262 MB)
sda: Write Protect is off
sda: sda1
WARNING: USB Mass Storage data integrity not assured
USB Mass Storage device found at 2
USB Mass Storage support registered.
usb.c: USB disconnect on device 00:1d.7-6 address 2

Make note of the line:
sda: sda1
This is the device your system is using.

If it doesn't work then try this: 
mount -t vfat /dev/sda1 /mnt/usb 

If it still doesn't work try this (some usb keys don't have a partition table on them): 
mount -t vfat /dev/sda /mnt/usb

If this still doesn't work, try to reload the modules:
modprobe -r usb-storage 
modprobe usb-storage

Then try to mount again.

2015年9月6日 星期日

fatal: Path 'XXX' is in submodule 'YYY' when git add

$ git ls-tree HEAD YYY 
 160000 commit c0f065504bb0e8cfa2b107e975bb9dc5a34b0398  mysubmodule 
That doesn't depend on the presence of the .gitmodule file, or on the content of mysubmodule.

You need to remove that entry from the index first:
$ git rm --cached YYY

2015年9月2日 星期三

vi內按方向鍵會出現ABCD

echo "set nocompatible" > ~/.vimrc

2015年8月11日 星期二

What does 'set -e' do, and why might it be considered dangerous?


Source: http://serverfault.com/questions/143445/what-does-set-e-do-and-why-might-it-be-considered-dangerous

set -e causes the shell to exit if any subcommand or pipeline returns a non-zero status.

The answer the interviewer was probably looking for is:

It would be dangerous to use "set -e" when creating init.d scripts:
From http://www.debian.org/doc/debian-policy/ch-opersys.html 9.3.2 --

Be careful of using set -e in init.d scripts. Writing correct init.d scripts requires accepting various error exit statuses when daemons are already running or already stopped without aborting the init.d script, and common init.d function libraries are not safe to call with set -e in effect. For init.d scripts, it's often easier to not use set -e and instead check the result of each command separately.
This is a valid question from an interviewer standpoint because it gauges a candidates working knowledge of server-level scripting and automation

How to identify Linux kernel verion ?


In kernel source tree, check top makefile.
For ex:
VERSION = 3
PATCHLEVEL = 1
SUBLEVEL = 0
EXTRAVERSION = -pax
NAME = Custom Pax Version
Or,
$ make kernelversion

In distribution shell,
$ uname -a

How to run 32-bit app in Ubuntu 64-bit?


When an executable exists but shell replies "No such file or directory",
check the executable by
    $ source
check the Linux architecture by
    $ uname -a

How to run 32-bit app in Ubuntu 64-bit?

To run a 32-bit executable file on a 64-bit multi-architecture Ubuntu system, you have to add the i386 architecture and install the three library packages libc6:i386, libncurses5:i386, and libstdc++6:i386:
    $ sudo dpkg --add-architecture i386

Or if you are using Ubuntu 12.04 LTS (Precise Pangolin) or below, use this:
    $ sudo echo "foreign-architecture i386" > /etc/dpkg/dpkg.cfg.d/multiarch
 Then:
    $ sudo apt-get update 
    $ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386

After these steps, you should be able to run the 32-bit application.

2015年8月8日 星期六

Linux 'find' handbook

#Exclude a directory in find . command
find . -path ./misc -prune -o -name '*.txt'
find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -o -print
find / -xdev -name p2p_supplicant.conf

#List all .bin (case ignored) and .txt (case sensitivity) files in /fooA and /fooB folders.
find /fA /fB -type f -iname "*.bin" -name "*.txt"
find -name "[a-z]*[4-9].log"
Copy all .txt files in /foo to ~/txt folder.
find /foo -type f -name "*.txt" -exec cp {} ~/txt \;
Remove all .git folders in /foo 
find /foo -type d -name ".git" -exec rm -fr {} \;    


List all hidden folders/files in /foo 
find /foo -name ".*" -ls    

# Find files and tar them (with spaces)
# It will:
#   + deal with files with spaces, newlines, leading dashes, and other funniness
#   + handle an unlimited number of files
#   + won't repeatedly overwrite your backup.tar.gz like 
#       using tar -c with xargs will do when you have a large number of files.
find . -type f -print0 | tar -czvf backup.tar.gz --null -T -
# Find files and open them in gedit.
find . -name '*.foo' -exec gedit {} +

# Find symbolic links but those inside .git folders and count.
find . ! -path "*/.git/*" -type l | wc -l
find . ! -path "*/.git/*" -type f -name "*.js" ! -name "*-min-*" ! -name "*console*"

Find files by text in the file (find + grep)
----------------------------------------------------------------------------------------------
# Find StringBuffer in all *.java files 
find -type f -name "*.java" -exec grep -l StringBuffer {} \;
# ignore case with -i option 
find -type f -name "*.java" -exec grep -il string {} \;
# search for a string in gzip'd files
find -type f -name "*.gz" -exec zgrep 'GET /foo' {} \;        


Find files by modification time
---------------------------------------------------------------------------------------------- 
find -newer A.log ! -newer B.log     # newer than A.log but no newer than B.log
find . -mtime 1                                 # 24 hours 
find . -mtime -7                                # last 7 days
touch -t YYMMDDhhmm.SS /tmp/timestamp
find directory -type f -newer /tmp/timestamp
rm /tmp/timestamp
touch –date "2012-11-07" /tmp/find_after
find / -newer /tmp/find_after
rm /tmp/find_after

Find files by user/group
---------------------------------------------------------------------------------------------- 
find /etc -user peida
find /home -nouser
find /apps -group sudo
find /apps -nogroup
find -perm 755                                # List all files/folders of permission 755
find /dir -type d -iname ".*" -ls      # List all files/folders in hidden folders.

find \! -user foo -print                     # List items NOT owned by user foo.

Find files by size,folder depth,partition
---------------------------------------------------------------------------------------------- 
find -size +1000000c                      # list items of size larger than 10^6 bytes.
find -name A*.txt -depth                 # list in the same depth and then subfolders.
find -name *.XC -mount                  # only for the same partition.


Error handling
----------------------------------------------------------------------------------------------
#ERROR find: paths must precede expression
find . -name "*.log"                     
#Handle file with space in its name.  ('find' treats SPACE, TAB, and NEWLINE as delimiter by default)
find . -name "*.log" -print0 | xargs -0 cat           #'-print0' append 0 rather than NEWLINE to the output string.  '-0' takes only 0 as delimiter.
find . -name "*.log" -print0 | xargs -d "\\n" cat  # ' -d "\\n" ' takes only NEWLINE as delimiter.

#Skip “Permission denied” errors
source: https://unix.stackexchange.com/questions/42841/how-to-skip-permission-denied-errors-when-running-find-in-linux
find / -name art  2>&1 | grep -v "Permission denied"
Explanation:
In short, all regular output goes to standard output (stdout). All error messages to standard error (stderr).
grep usually finds/prints the specified string, the -v inverts this, so it finds/prints every string that doesn't contain "Permission denied". All of your output from the find command, including error messages usually sent to stderr (file descriptor 2) go now to stdout(file descriptor 1) and then get filtered by the grep command.
This assumes you are using the bash/sh shell.
Under tcsh/csh you would use
 find / -name art |& grep ....


To Be Sorted

---------------------------------------------------------------------------------------------- 
删除以html结尾的10天前的文件,包括带空格的文件:
find /usr/local/backups -name "*.html" -mtime +10 -print0 |xargs -0 rm -rfv
find /usr/local/backups -mtime +10 -name "*.html" -exec rm -rf {} \;

find -print 和 -print0的区别:
-print 在每一个输出后会添加一个回车换行符,而-print0则不会。

当前目录下文件从大到小排序(包括隐藏文件),文件名不为".":
find . -maxdepth 1 ! -name "." -print0 | xargs -0 du -b | sort -nr | head -10 | nl
nl:可以为输出列加上编号,与cat -n相似,但空行不编号
以下功能同上,但不包括隐藏文件:
for file in *; do du -b "$file"; done|sort -nr|head -10|nl

xargs结合sed替换:
find . -name "*.txt" -print0 | xargs -0 sed -i 's/aaa/bbb/g'

xargs结合grep:
find . -name '*.txt' -type f -print0 |xargs -0 grep -n 'aaa' #“-n”输出行号

Find things by name

 # find /path/to/search -name filename

Example
 # find /etc -name hosts
  /etc/hosts

Find things by name (case-insensitive)

 # find /path/to/search -iname filename

Example
 # find /etc -iname HOSTS
  /etc/hosts

Find only files by name

 # find /path/to/search -name filename -type f

Example
 # find /etc -name network* -type f
  /etc/init/networking.conf

Find only directories by name

 # find /path/to/search -name dirname -type d

Example
 # find /etc -name network* -type d
  /etc/apparmor/init/network-interface-security

Find all symlinks

 # find /path/to/search -type l

Example
 # find /etc -type l
  /etc/vtrgb

Find things by owner

 # find /path/to/search -user owner

Example
 # find ./ -user root
  ./
  ./log.file

Find executable files

 # find /path/to/search -type f -executable

Example
 # find ./ -type f -executable
 ./4/2651.file

Find SUID files

 # find /path/to/search -perm -4000

Example
 # find /sbin -perm -4000
 /sbin/mount.ecryptfs_private

Find things changed today

 # find /path/to/search -daystart -ctime -1

Example
 # find ./ -daystart -ctime -1
  ./

Find things changed in the last 24 hours

 # find /path/to/search -ctime -1

Example
 # find ./ -ctime -1
  ./

Counting how many things you find

 # find /path/to/search | wc -l

Example
 # find ./ | wc -l
  14674

Deleting things you find

 # find /path/to/search -delete

Deleting things you find (with xargs)

 # find /path/to/search | xargs rm

Deleting things you find (with exec)

 # find /path/to/search -exec rm {} ;

Printing Type of file, Filename & Inode

 # find /path/to/search -printf "%y %i %prn"

Example
 # find ./ -printf "%y %i %prn"
  d 4852409 ./

Finding Broken Symlinks

 # find /path/to/search -follow -lname "*"

Example
 # find ./ -follow -lname "*"
  ./bad_link

Find files older than 31 days and delete them

 # find /path/to/search -mtime +31 -delete

Example
 # find ./ -mtime +31
  ./sudoers.new
  ./file.symlink
  ./somedirectory
  ./play/list.txt2
  ./tar.tgz
  # find ./ -mtime +31 -delete
  # find ./ -mtime +31

Remove Empty Directories

 # find /path/to/search -type d -exec rmdir --ignore-fail-on-non-empty {} + ;

Tar files changed today

 # tar -cvzf ../files_created_today.tgz `find /path/to/search -type f -daystart -ctime -1`

Find files bigger than X Size

 # find /path/to/search -size +

Example
 # find ./ -size +100M
 ./madflojo/Downloads/ubuntu-12.04-server-amd64.iso

Using Regex with find

 # find /path/to/search -regex 'regex pattern (full path)'

Example
 # find /var -regex '.*/tmp/.*[0-9]*.file'
 /var/tmp/testing/2/914.file

Ubuntu下的中文輸入(ibus)


System Settings > Language Support > Keyboard input method system > ibus

If there is no keyboard icon is shown in the system tray, do "ibus-daemon -x -r -d"

Click on this keyboard icon > Preferences > Input Method > Check Customize active input methods ...

Key to toggle the input method : CTRL + SPACE.
Key to select: ALT +
Key to select the highlighted term: SPACE

2015年7月23日 星期四

Python 的 .py 和 .pyc 檔有什麼不同 ?


Source: http://www.arthurtoday.com/2010/02/python-py-pyc.html

Python 的程式是寫在 .py 裡,也就是說, .py 檔是 Python 的原始程式碼檔案,而 Python 會在執行 .py 檔時,將 .py 的程式碼編譯成中間程式碼檔 ( byte-compiled ) 的 .pyc 檔以加快下次執行的速度。

所以,當你執行一支 .py 檔時,Python 會先看看有沒有這支 .py 檔的 .pyc 檔,如果有,而且 .py 檔的修改時間和 .pyc 檔一樣時,Python 就會讀 .pyc 檔,否則,Python 就會去讀原來的 .py 檔。

不過,執行 .py 檔並不一定會產生出 .pyc 檔,通常是被 import 的 module 的 .py 檔才會產生出 .pyc 檔的

2015年7月22日 星期三

apt-get fails due to *openssl*


install libcurl4-openssl-dev pass
 
Command:
sudo apt-get remove --purge libcurl4-openssl-de
sudo dpkg -i --force-overwrite /var/cache/apt/archives/libssl-dev_1.0.1-4ubuntu5.31_i386.deb
sudo apt-get autoremove
sudo apt-get update
sudo apt-get install libcurl4-openssl-dev
sudo dpkg --configure -a
 

error: gnutls_handshake() failed: A TLS packet with unexpected length was received.

>>> Issue
error: gnutls_handshake() failed: A TLS packet with unexpected length was received. while accessing ...
fatal: HTTP request failed


<<< Fix
sudo apt-get install build-essential fakeroot dpkg-dev
mkdir ~/git-openssl
cd ~/git-openssl
sudo apt-get source git
sudo apt-get build-dep git
sudo apt-get install libcurl4-openssl-dev
sudo dpkg-source -x git_1.7.9.5-1.dsc
cd git_1.7.9.5

Then, edit debian/control file (run the command: gksu gedit debian/control) and replace all instances of libcurl4-gnutls-dev with libcurl4-openssl-dev.

Then build the package (if it's failing on test, you can remove the line TEST=test from the file debian/rules):

sudo dpkg-buildpackage -rfakeroot -b

Install new package:
i386:  sudo dpkg -i ../git_1.7.9.5-1_i386.deb
x86_64: sudo dpkg -i ../git_1.7.9.5-1_amd64.deb

List all versions of a given source packages.

$ apt-cache madison

GPG error: The following signatures were invalid: BADSIG 16126D3A3E5C1192 Ubuntu Extras Archive Automatic Signing Key

>>> Issue
W: GPG error: http://extras.ubuntu.com precise Release: The following signatures were invalid: BADSIG 16126D3A3E5C1192 Ubuntu Extras Archive Automatic Signing Key

<<< Fix #1 (NG)
sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 16126D3A3E5C1192

<<< Fix #2 (OK)
sudo -i
apt-get clean
cd /var/lib/apt
mv lists lists.old
mkdir -p lists/partial
apt-get clean
apt-get update
This will rebuild the cache !