Перейти к главному содержимому

bash и аргументы командной строки

Пример разбора нескольких опций командной строки

VERBOSE=
NINGEN_OPTS=

function usage {
        echo "Usage: $(basename $0) [-hwv] [-n ningen_opts]" 2>&1
        echo '   -h   shows usage'
        echo '   -v   set verbose mode ON'
        echo '   -w   build for windows (using mingw on linux)'
        echo '   -n   options passed to ningen'
        exit 1
}

while getopts ":hvwn:" opt; do
  case ${opt} in
    #-----------------------------
    h ) usage ;;
    v ) VERBOSE="-v" ;;
    w ) BUILD_FOR_WINDOWS=1 ;;
    n ) NINGEN_OPTS=$OPTARG ;;
    #-----------------------------
    \? )
      echo "Invalid Option: -$OPTARG" 1>&2
      exit 1
      ;;
    :)                                    # If expected argument omitted:
      echo "Error: -${OPTARG} requires an argument."
      exit 1                              # Exit abnormally.
      ;;
    *)                                    # If unknown (any other) option:
      usage                               # Exit abnormally.
      ;;
  esac
done
shift $((OPTIND -1))

# берем первый аргумент из списка - директория на сервере куда копировать
#TARGET_DIR="$1"
#shift

echo "Main script running"

Отказ запуска без аргументов

Для того, чтобы обработать случай отсутствия аргументов, после usage добавить:

if [[ ${#} -eq 0 ]]; then
   usage
fi

Несколько приёмов для bash

Запуск python в зависимости от платформы

Требуется под linux запускать python как python3, а под windows как python

В скрипте можно сделать так:

if [[ "$OSTYPE" == "linux"* ]]; then
  PY=python3
else
  PY=python
fi

В дальнейшем коде запускать $PY вместо python.

Возврат кода ошибки

Чтобы вернуть код ошибки из одного и того же скрипта может быть два варианта:

  • скрипт запустили прямо из bash
  • скрипт вызвали из другого скрипта

Если скрипт запустили прямо из bash, то надо использовать exit, а если из другого скрипта, то с высокой долей вероятности требуется return.

Можно это делать автоматически:

### define $ret command as 'exit' if run standalone or
### define $ret command as 'return' if called from another script
[[ "$0" == "$BASH_SOURCE" ]] && ret=exit || ret=return

Потом это можно использовать примерно так:

mysupercommand || $ret $? 

или

$ret 1

Присвоить значение переменной если такой переменной ещё нет

[ -z "${OUTDIR}" ] && OUTDIR=__output

ну или полноценное условие если переменной не существует

if [[ -z "${USE_VAR}" ]]; then
  echo "### No USE_VAR defined"
else
  echo "### USE_VAR = ${USE_VAR}"
  ......
fi

Дополнение строковой переменной новой строкой

MYVAR=

MYVAR+=$'\n'
MYVAR+="string number 1"


MYVAR+=$'\n'
MYVAR+="string number 2"

echo "${MYVAR}"

Конфигурационный файл latexmkrc

latexmk ищет настройки, помимо параметров командной строки, в файле конфигурации latexmkrc.

Вот его типовое содержимое:

# Jobname: as with current tex, etc indicates basename of generated files.
$jobname = 'trd'; 

$out_dir = '__output';  # Directory for output files.

# Array of LaTeX files to process when no files are specified on the command line.
# Wildcards allowed
@default_files = ('main.tex');

$diagnostics = 0;

$pdf_mode = 1;  # No pdf file requested to be made by pdflatex
                # Possible values: 
                #     0 = don't create pdf file
                #     1 = pdflatex to create pdf file by pdflatex
                #     2 = pdf from ps by ps2pdf
                #     3 = pdf from dvi by dvipdf
                #     4 = lualatex    
                #     5 = xelatex     

$do_cd = 0;     # Do not do cd to directory of source file.


$force_mode = 0;        # =1 to force processing past errors

$recorder = 1;          # Whether to use recorder option on latex/pdflatex
$silent = 0;            # Silence latex's messages?


push @extra_pdflatex_options, '-file-line-error';
push @extra_xelatex_options, '-file-line-error';

#push @extra_pdflatex_options, '-halt-on-error';
#push @extra_pdflatex_options, '-interaction=batchmode';
#push @extra_pdflatex_options, '-synctex=1';

$dependents_list = 0;   # Whether to display list(s) of dependencies
$dependents_phony = 0;
$rules_list = 0;        # Whether to display list(s) of dependencies
$deps_file = $out_dir . '/' . $jobname . '.dep';       # File for dependency list output.  Default stdout.

$clean_ext = "dep gz";  # space separated extensions of files that are
                        # to be deleted when doing cleanup, beyond
                        # standard set

$show_time = 1;

if ( ! exists $ENV{TEXINPUTS} ) {
  $ENV{TEXINPUTS} = '';
}
$ENV{TEXINPUTS} = '../sty'.$search_path_separator.$ENV{TEXINPUTS};

Цикл по строкам или файлам и каталогам в bash

Однострочник - выполнение команды в цикле

while true; do echo 'Hit CTRL+C'; sleep 1; done

Цикл по массиву строк

#!/bin/bash

####################################
# Массив строк с именем "arrayname"
####################################
arrayname=( one two three )

####################################
# Цикл по элементам массива
####################################
for i in "${arrayname[@]}"
do
    echo "$i"
done

Цикл по файлам и каталогам

#!/bin/bash

################################
# Цикл по файлам и каталогам
################################
for v in ../src/*
do
  echo "$v"
done

Цикл по каталогам c формированием списка в переменной

#!/bin/bash

################################
# Пустой список каталогов
all_dirs=""

################################
# Цикл по каталогам
################################
for v in ../src/*
do
  if [ -d "$v" ]; then
    echo "$v"
    # Дополнение списка каталогов (разделитель - перенос строки)
    all_dirs+="$v"$'\n'
  fi
done

echo "----"

echo "$all_dirs"

gitlab CI config

Пример конфигурации gitlab-CI для репозитория.

Файл .gitlab-ci.yml в корне репозитория

###############################################################################
stages:
  - build
  - prepare
  - deploy

###############################################################################
variables:
#  GIT_SSL_NO_VERIFY: "1"
#  GIT_SUBMODULE_STRATEGY: recursive
#  GIT_STRATEGY: fetch
  ## !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  DEPLOY_PATH_PREFIX: superproject

###############################################################################
#------------------------------------------------------------------------------
build:linux32:
  stage: build
  tags:
    - linux, gcc32
  script:
    - echo "build commands"
  artifacts:
    paths:
    - build/bin32/*
    expire_in: 1 hour

#------------------------------------------------------------------------------
build:linux64:
  stage: build
  tags:
    - linux, gcc64
  script:
    - echo "build commands"
  artifacts:
    paths:
    - build/bin64/*
    expire_in: 1 hour

#------------------------------------------------------------------------------
build:doc:
  stage: build
  tags:
    - latex
  script:
    - cd doc
    - latexmk
  artifacts:
    paths:
    - doc/result/*
    expire_in: 1 hour

###############################################################################
prepare_release:
  stage: prepare
  tags:
    - linux, gcc
  script:
    - mkdir release
    - mkdir release/doc
    - mkdir release/bin
    - cp doc/result/*  release/doc/
    - cp build/bin32/* release/bin/
    - cp build/bin64/* release/bin/
  dependencies:
    - build:doc
    - build:linux64
    - build:linux32
  artifacts:
    paths:
    - release/*
    expire_in: 2 hours

###############################################################################
upstream:
  stage: deploy
  trigger:.
    project: upstream/project1
    branch: master
#------------------------------------------------------------------------------
deploy_testing:
  variables:
    GIT_SUBMODULE_STRATEGY: none
  stage: deploy
  tags:
    - dev-deploy
  except:
    - tags
  script:
    - deploy_to_dev -b -d $DEPLOY_PATH_PREFIX release/
  dependencies:
    - prepare_release

#------------------------------------------------------------------------------
deploy_tag:
  variables:
    GIT_SUBMODULE_STRATEGY: none
  stage: deploy
  tags:
    - dev-deploy
  only:
    - tags
  script:
    - deploy_to_dev -v $DEPLOY_PATH_PREFIX release/
  dependencies:
    - prepare_release