linux


常用的命令介绍

ls

ls(英文全拼: list directory contents)命令用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录)。
ls [-alrtAFR] [name...]
参数 :

  • -a 显示所有文件及目录 (. 开头的隐藏文件也会列出)
  • -d 只列出目录(不递归列出目录内的文件)
  • -l 除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出
  • -r 将文件以相反次序显示(原定依英文字母次序)
  • -t 将文件依建立时间之先后次序列出
  • -A 同 -a ,但不列出 "." (目前目录) 及 ".." (父目录)
  • -F 在列出的文件名称后加一符号;例如可执行档则加 "*", 目录则加 "/"
  • -R 若目录下有文件,则以下之文件亦皆依序列出

ll

ll其实就是ls -l的别名,示例如下

drwxr-xr-x 2 root  root       4096 2023-02-07 17:24:46 test
-rwxr-xr-x 1 root  root        172 2022-10-31 10:39:55 test1.sh
-rwxrwxrwx 1 root  root         68 2022-12-05 15:27:15 test2.sh
-rwxr-xr-x 1 root  root         30 2023-02-06 19:37:36 test3.sh
-rwxr-xr-x 1 root  root        230 2022-10-31 10:11:25 test.sh
  1. 第1位表示文件的类型,-:普通文件, d:目录文件,p:管理文件,l:链接文件,b:块设备文件,c:字符设备文件,s:嵌套字文件。
  2. 第2、3、4位表示所有者/所有者权限,r:读权限,w:写权限,x:可执行权限,-:无权限,read4,write2,execute1。
  3. 第5、6、7位表示组用户权限(一个组中除所有者拥有的权限)。
  4. 第8、9、10位表示其他用户权限(除当前所有者的组,其他组可以进行访问的权限)。
  5. 这一列数字表示:如果是普通用户这个数字指的是链接数,如果是目录文件这个数字指的是它的第一级子目录数。
  6. 用户名
  7. 组名
  8. 文件大小(字节)
  9. 最后修改时间
  10. 文件名

grep

全拼:Global search REgular expression and Print out the line.
文本搜索工具,根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查,打印匹配到的行.
grep [options] [pattern] file
参数:

  • -c 仅列出文件中包含模式的行数。
  • -i 忽略模式中的字母大小写。
  • -l 列出带有匹配行的文件名。
  • -n 在每一行的最前面列出行号。
  • -v 列出没有匹配模式的行。
  • -w 把表达式当做一个完整的单字符来搜寻,忽略那些部分匹配的行。

sed

awk

xargs

tail

ps

ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。
参数:

  • -A 显示所有的进程,跟-e的效果相同
  • -a 显示现行终端机下的所有进程,包括其他用户的进程
  • -u 显示当前用户的进程状态
  • -x 通常与 a 这个参数一起使用,可列出较完整信息
  • -l 较长、较详细的将该PID的信息列出
  • -j 工作的格式(jobs format)
  • -f 把进程的所有信息都显示出来
  • -e 表示显示所有继承

cat

wc


工作上常用的一些姿势

查看端口占用并杀死进程

ps -aux |grep java
ps -ef |grep java
netstat -anp |grep 端口号
lsof -i :端口号
kill -9 进程号

动态查看日志内容

tail -100f console.log

查找文件内容中关键字

在vim中打开

/关键字 回车,按n向下查找,N向上查找

未打开时

grep 关键字 文件名
cat 文件名 | grep 关键字

查找目录下包含关键字的文件内容

grep -r 关键字 目录

启动jar包的shell

#! /bin/bash
CURRENT_PATH=$(cd $(dirname $0); pwd)
JAR=$(find $CURRENT_PATH -maxdepth 1 -name "*.jar")
PID=$(ps -ef | grep $JAR| grep -v grep | awk '{ print $2 }')

JAVA_OPTIONS="-Dfile.encoding=UTF-8  -Xmx2048m -Xms2048m -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=xxxx"
STARTFLAG="Application {0} is running! Access URLs"
function read_log
{
    echo "$JAR service boot console.log read"
    tail -100f console.log|while read line
    do
    result=`echo "$line"|grep "$STARTFLAG" |wc -l`
    if [ $result -eq 1 ]; then
        echo "$JAR service boot success"
        break

    fi
    done
    echo "$JAR service boot 退出日志打印"
    exit 0

}
case "$1" in
    start)
        if [ ! -z "$PID" ]; then
            echo " $JAR is already online ,PID : $PID"
        else
            echo -n -e "booting $JAR ... \n"
            rm -f $CURRENT_PATH/console.log
            nohup java -jar $JAVA_OPTIONS $JAR > console.log 2>& 1 &
            if [ "$?" = "0" ]; then
                echo "$JAR service boot success,please check console.log"
                read_log
            else
                echo "$JAR service boot failure,view console.log for more information"
            fi
        fi
        ;;
    stop)
        if [ -z "$PID" ]; then
            echo "$JAR is not running ... shutdown failure"
        else
            echo "$JAR shutting down"
            kill -9 $PID
            if [ "$?"="0" ];then
                echo "Service shutdown success"
            else    
                echo "Service shutdown failure"
            fi
        fi
        ;;
    restart)
        sh ${0} stop
        sh ${0} start
        ;;
    status)
        if [! -z "$PID"]; then
            echo "$JAR ONLINE"
        else
            echo "$JAR OFFLINE"
        fi
        ;;
    *)
        sh ${0} stop
        sh ${0} start
esac

遇到的问题

shell无法执行

在执行shell脚本的时候,报错:/bin/bash^M: bad interpreter: No such file or directory。是由于该脚本文件是在Windows平台编写,然后在MacOS平台中执行。Windows平台上文件是dos格式,换行符尾\r\n,而MacOS平台文件是unix格式,换行符尾\n。因此在运行脚本文件时,不能正确解析\r,导致编译错误、运行失败。在MacOS平台上,打开命令行工具执行命令vim *.sh(编辑你的脚本文件),然后执行命令:set ff=unix,最后执行:wq( 保存退出)即可。


Oracle

常用命令

查询相关

-------查询字段长度-----------
select length() from 
--------------查询数量-------
select count(1) from 
----------substr------------
select concat(substr(``,1,3),substr(``,4,6)) from 
----------分组查询---------
select distinct(``),sum(``) over(partition by ``) from 
----------查询字段重复的数据---------
select columnname from tablename group by columnname having count(columnname)>1
----------max,min---------
select max(),min() from 
----------分组查询first_value----------
select distinct(),first_value() over(partition by `` order by `` desc) from 
----------根据分组查询排序-------------
select rank() over(partition by `` order by `` desc) as rank from  --值相同排名相同,后续跳跃
select dense_rank() over(partition by `` order by `` desc) as rank from --值相同排名相同,后续连续
select row_number() over(partition by `` order by `` desc) as rank from --单纯排序
------------查询随机数---------
select trunc(dbms_random.value(0,365)) as rn from dual
------------查询随机数据---------
select * from (select * from table_name order by dbms_random.value) where rownum<=(select ceil(count(1)*0.05) as num from table_name);
------------查询当前日期加减------------
select sysdate from dual;
select sysdate+numtodsinterval(1,'day') as res from dual;
select sysdate+numtodsinterval(-1,'day') as res from dual;
select sysdate-numtodsinterval(1,'day') as res from dual;
select sysdate+numtodsinterval(24*3600,'second') as res from dual;
select sysdate+numtoyminterval(1,'month') as res from dual;
select sysdate+numtoyminterval(1,'year') as res from dual;
--------------查询当前日期的月份最后一天-----------
select last_day(sysdate+31) from dual;
--------------查询当前日期的月份第一天-----------
select trunc(sysdate,'MM') from dual;
--------------查询某个字段长度最长的值-------------
select ``,length(``) from  where length(``)=(select max(length(``)) from )
--------------查询被锁的会话id-----------------
select session_id from v$locked_object;
-------------查询会话id详细信息---------------
select sid,serial#,username,osuser from v$session where sid=6;
select sid||','||serial as ss from (select distinct a.sid,a.serial# as serial from v$session a,(select session_id from v$locked_object)b where sid=b.session_id)c;

删除相关

--------------删除数据------------
delete from tablename where 条件
------------清空表数据-----------
truncate table tablename
------------删除分区------------
alter table   tablename   drop partition ;
------------彻底删除表----------
drop table  tablename  purge;
------------将锁定的会话关闭,格式为'sid,serial'----------
alter system kill session ',';

更新相关

-------------更新字段值-------------
update table_name set a='',b='' where
update table_name set (a,b)=(select '','' from dual) where

修改相关

alter table  tablename add  columnname vachar(20) default TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS') NOT NULL ;----增加字段
alter table  tablename  modify --修改字段
alter table  tablename  drop columnname ---删除字段

插入相关

---------------插入数据------------
insert into tablename   (,,,) values (,,,),(,,,);
-------------插入表数据--------------
insert into tablename select * from  tablename;

项目收获

临时表

事务级临时表,commit后清空。

create global temporary table tmp_user (
  user_id   varchar2(10),
  user_name varchar2(20)
) on commit delete rows; --------------commit后清空。

会话级临时表,commit后数据还在,但是数据只在这个会话存在,新建一个会话查询是没有的。

create global temporary table tmp_user1 (
  user_id   varchar2(10),
  user_name varchar2(20)
)on commit preserve rows;------------commit后数据还在,但是数据只在这个会话,新建一个会话是没有的。

自动分区

创建一个自动分区只需要建表时加上一句,其中自动分区的字段一定是整数或者日期类型,创建分区的间隔可以根据自己的需要进行修改,同时默认分区是必须的。

partition by range (INPUT_DATE) INTERVAL (NUMTODSINTERVAL(1,'day'))
(partition part_t01 values less than(to_date('2018-12-12','yyyy-mm-dd')));

select * from user_tab_partitions where table_name='';--------查询表分区------------
alter table tablename  drop partition;---------删除分区------------
select * from user_ind_partitions;---------查询分区索引---------

在java程序中自动删除n天前的分区还是需要费点功夫的,用我在项目中的例子。首先要获取这个表的所有分区名称和值,用list存储。

select PARTITION_NAME,HIGH_VALUE from user_tab_partitions where table_name='FIVE_DETAIL_INFO';

假如我要自动删除n天前的数据(这个n值可以从数据库中配置并获取),那么我就要写个循环匹配在当前跑批日期前n天的分区是否存在,如果存在就删除,要注意还要大于默认分区的值。这个HIGH_VALUE是有规律的按时间增长的,我们可以截取字符后进行匹配,还需要注意的一点是这个值是大一天的,比如我在2023-02-10的数据插入进去后值为TO_DATE(' 2023-02-11 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')。获取到PARTITION_NAME就可以执行删分区语句了alter table five_detail_info drop partition SYS_P141
贴上service层的语句过程:

/**
*删除指定日期n天前的分区
**/
public void deletePartitionByDate(String date) throws ParseException {
    /**
    *获取表的所有分区名称和值
    **/
    List<FiveDetailInfo> list = fiveDetailInfoMapper.selectPartitionName(date);
    
    /**
    *把字符串date转换成日期类型减n天并加1天,再转回字符串类型
    **/
    Date newDate = new SimpleDateFormat("yyyy-MM-dd").parse(date);
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(newDate);
    int n = fiveDetailInfoMapper.findDictionaryN();
    calendar.add(Calendar.DAY_OF_MONTH, -n+1);//因为分区的值要多1天
    String newDateStr = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    /**
    *根据分区值和日期找到分区名称并删除
    **/
    logger.info("----------开始查找FIVE_DETAIL_INFO表"+n+"天前的分区"---------------");
    if (list.size() >0){
        Iterator<FiveDetailInfo> it = list.iterator();
        FiveDetailInfo fiveDetailInfo = it.next();
        while (it.hasNext()){
            FiveDetailInfo next =it.next();
            String str = next.getHighValue().substring(10,20);//截取yyyy-MM-dd部分
            if (str.compareTo(newDateStr)<=0&&str.compareTo("2018-12-12")>0) {
                fiveDetailInfoMapper.deleteByPartitionName(next.getPartitionName());
                Date tempDate=new SimpleDateFormat("yyyy-MM-dd").parse(str);
                Calendar tempDate= Calendar.getInstance();
                tempCalendar.setTime(tempDate);
                tempCalendar.add(Calendar.DAY_OF_MONTH,-1);//因为分区值是T+1的,所以减一天才是真正的日期
                String tempDateStr = new SimpleDateFormat("yyyy-MM-dd").format(tempCalendar.getTime());
                logger.info("删除日期为"+tempDateStr+"的分区成功");
            }
        }
    }

}

存储过程

找出脏数据

借据表中主键为借据号,不同的人(cust_id)不能有相同的收款账号(loanacno_real),同一个人不同借据号可以有相同的收款账号,现在表中有脏数据:不同的人有了相同的收款账号,构造查询:

select loan_ac_no,cust_id,cust_name,loanacno_real 
from biz_loan_info_detail 
where loanacno_real in (select loanacno_real 
                        from (select loanacno_real 
                              from biz_loan_info_detail 
                              group by (loanacno_real,cust_id)) 
                        group by (loanacno_real) 
                        having count(loanacno_real) >1);

同理,客户表中,不同的人(party_id)不能有相同的身份证号(cert_no),查询脏数据:

select party_id,party_name,cert_no 
from cus_basic_info 
where cert_no in (select cert_no 
                  from (select party_id,cert_no 
                        from cus_basic_info 
                        group by (party_id,cert_no)) 
                  group by (cert_no) 
                  having count(cert_no)>1);