diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..fcf0211
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/bioinfor_tools.iml b/.idea/bioinfor_tools.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/bioinfor_tools.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..4e6a219
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d56657a
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..4851e72
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b71352e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# bioinfor_tools
+
diff --git a/bioinfor_tools.egg-info/PKG-INFO b/bioinfor_tools.egg-info/PKG-INFO
new file mode 100644
index 0000000..e3954ea
--- /dev/null
+++ b/bioinfor_tools.egg-info/PKG-INFO
@@ -0,0 +1,12 @@
+Metadata-Version: 2.1
+Name: bioinfor-tools
+Version: 0.1
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: jmzhang
+Author-email: jmzhang1911@gmail.com
+License: UNKNOWN
+Platform: UNKNOWN
+
+UNKNOWN
+
diff --git a/bioinfor_tools.egg-info/SOURCES.txt b/bioinfor_tools.egg-info/SOURCES.txt
new file mode 100644
index 0000000..a3995f2
--- /dev/null
+++ b/bioinfor_tools.egg-info/SOURCES.txt
@@ -0,0 +1,9 @@
+setup.py
+bioinfor_tools/__init__.py
+bioinfor_tools/_bio_basic.py
+bioinfor_tools/_cmd_runner.py
+bioinfor_tools/_utils.py
+bioinfor_tools.egg-info/PKG-INFO
+bioinfor_tools.egg-info/SOURCES.txt
+bioinfor_tools.egg-info/dependency_links.txt
+bioinfor_tools.egg-info/top_level.txt
\ No newline at end of file
diff --git a/bioinfor_tools.egg-info/dependency_links.txt b/bioinfor_tools.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/bioinfor_tools.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/bioinfor_tools.egg-info/top_level.txt b/bioinfor_tools.egg-info/top_level.txt
new file mode 100644
index 0000000..b728b9c
--- /dev/null
+++ b/bioinfor_tools.egg-info/top_level.txt
@@ -0,0 +1 @@
+bioinfor_tools
diff --git a/bioinfor_tools/__init__.py b/bioinfor_tools/__init__.py
new file mode 100644
index 0000000..620c813
--- /dev/null
+++ b/bioinfor_tools/__init__.py
@@ -0,0 +1,19 @@
+#!/share/nas2/genome/biosoft/Python//3.7.3/bin/python3
+# -*- coding: utf-8 -*-
+# @Time : 2023/4/28 09:13
+# @Author : jmzhang
+# @Email : jmzhang1911@gmail.com
+
+import logging
+
+FORMAT = '%(asctime)s %(message)s'
+logging.basicConfig(level=logging.INFO, format=FORMAT, datefmt='%Y-%m-%d %H:%M:%S')
+
+__version__ = 'v0.1 beta'
+
+from ._bio_basic import BioBasic
+from ._cmd_runner import CmdRunner as __CmdRunner
+from ._utils import *
+
+cmd_wrapper = __CmdRunner.cmd_wrapper
+cmd = __CmdRunner.cmd
diff --git a/bioinfor_tools/__pycache__/__init__.cpython-39.pyc b/bioinfor_tools/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000..2ad1ad1
Binary files /dev/null and b/bioinfor_tools/__pycache__/__init__.cpython-39.pyc differ
diff --git a/bioinfor_tools/__pycache__/_bio_basic.cpython-39.pyc b/bioinfor_tools/__pycache__/_bio_basic.cpython-39.pyc
new file mode 100644
index 0000000..5633aa6
Binary files /dev/null and b/bioinfor_tools/__pycache__/_bio_basic.cpython-39.pyc differ
diff --git a/bioinfor_tools/__pycache__/_cmd_runner.cpython-39.pyc b/bioinfor_tools/__pycache__/_cmd_runner.cpython-39.pyc
new file mode 100644
index 0000000..a3c6d74
Binary files /dev/null and b/bioinfor_tools/__pycache__/_cmd_runner.cpython-39.pyc differ
diff --git a/bioinfor_tools/__pycache__/_utils.cpython-39.pyc b/bioinfor_tools/__pycache__/_utils.cpython-39.pyc
new file mode 100644
index 0000000..9d372ee
Binary files /dev/null and b/bioinfor_tools/__pycache__/_utils.cpython-39.pyc differ
diff --git a/bioinfor_tools/_bio_basic.py b/bioinfor_tools/_bio_basic.py
new file mode 100644
index 0000000..228353a
--- /dev/null
+++ b/bioinfor_tools/_bio_basic.py
@@ -0,0 +1,20 @@
+from pathlib import Path
+
+
+class BioBasic:
+ """
+ - basic functions and property
+ - read cfg
+ - mkdir dir
+ - module property
+ """
+ # 主路径位置
+ BASE_DIR = Path(__file__).absolute().parent.parent
+ # 日志路径
+ LOGGING_SUMMARY = BASE_DIR / 'logging_summary.txt'
+
+ def __init__(self, module):
+ # 模块所在的绝对父目录
+ self._module_dir = Path(module).absolute().parent
+ # 模块的名称
+ self._module_name = Path(module).name
diff --git a/bioinfor_tools/_cmd_runner.py b/bioinfor_tools/_cmd_runner.py
new file mode 100644
index 0000000..b52c475
--- /dev/null
+++ b/bioinfor_tools/_cmd_runner.py
@@ -0,0 +1,289 @@
+from concurrent.futures import ThreadPoolExecutor, wait, FIRST_EXCEPTION
+import bioinfor_tools._utils as _utils
+from ._bio_basic import BioBasic
+from threading import Event
+from pathlib import Path
+import subprocess
+import functools
+import datetime
+import getpass
+import logging
+import inspect
+import time
+
+
+class CmdRunner(BioBasic):
+ """
+ 1) basic
+ Note: cmd_container: ([cmd1, cmd2, *], *) or [cmd1, cmd2, *]
+ There are two ways to do it:
+ - @CmdRunner.cmd_wrapper(): the wrapper-ed function must return a cmd_container
+ - CmdRunner.runner(cmd_container): just use it as a function
+
+ example 01:
+
+ @CmdRunner.cmd_wrapper()
+ def hello_world():
+ cmd_list = ['sleep 5 && echo done' for _ in range(5)]
+ return cmd_list
+
+ example 02:
+ CmdRunner.runner(['echo hello world'])
+
+ 2) Using PBS: add parameter use_qsub=True
+ 3) outputs:
+ - cmds_sh:
+ - func_name-time.sh # contains cmds
+ - cmds_qsub:
+ - func_name-time
+ - cmd_1.pbs # pbs script
+ - cmd_1.xxx # means failure
+ - cmd_1.output # standard output
+ - cmd_1.error # standard error output
+ - cmd_1.done # means success
+ """
+
+ user_name = getpass.getuser()
+ qsub_nodes = 'hpc12-l-0-0'
+
+ # qsub的一些属性
+ _qsub_host = 'ssh {}@{} "cd {} && '.format(user_name, qsub_nodes, Path().absolute())
+ _qsub_re_submit_times = 2 # 重投次数
+ _qsub_check_time = 60 # 多久检查一次任务执行状况,单位:秒
+
+ subprocess_list = []
+
+ @staticmethod
+ def _resolve_cmd(cmd_container):
+ """
+ 解析cmd -> ([cmd1, cmd2, *], *) or [cmd1, cmd2, *]
+ """
+ if not cmd_container:
+ raise 'None cmd, shut down!!!'
+
+ if isinstance(cmd_container, list):
+ return cmd_container, None
+
+ elif isinstance(cmd_container, tuple) and isinstance(cmd_container[0], list):
+ return cmd_container[0], cmd_container[1:]
+
+ else:
+ raise Exception('please input ([cmd1, cmd2, *], *) or [cmd1, cmd2, *]')
+
+ @classmethod
+ def _run_shell(cls, cmd, use_qsub: bool, event, file_exist_for_skipping=''):
+ """
+ - 执行命令,可选普通shell模式或qsub模式
+ - qsub模式,通过qstat判断任务是否正在进行,运行完成后判断是否touch.done,若失败会重新运行三次
+ """
+ if not use_qsub:
+ logging.info('-> running {}'.format(cmd))
+
+ if event.is_set():
+ logging.info('Stopping, {}'.format(cmd))
+ return
+
+ p = subprocess.Popen(cmd, shell=True)
+ cls.subprocess_list.append(p)
+ # while True:
+ # if event.is_set():
+ # logging.info('Stopping, {}'.format(cmd))
+ # p.terminate()
+
+ ret = p.wait()
+
+ if ret != 0:
+ error_info = '-> `{}` failed:\n{}'.format(cmd, ret)
+ raise Exception(error_info)
+
+ else:
+ cmd_qsub, touch_done, cmd_shell = cmd
+ num = 1
+
+ while num <= cls._qsub_re_submit_times:
+ logging.info('-> qsub is running {}'.format(cmd_shell))
+ p = subprocess.Popen(cmd_qsub, shell=True, stdout=subprocess.PIPE)
+ p.wait()
+ job_number = p.stdout.read().decode().split()[2]
+
+ while True:
+ time.sleep(cls._qsub_check_time)
+ p1 = subprocess.Popen('qstat', shell=True, stdout=subprocess.PIPE)
+ msg = p1.stdout.read().decode()
+
+ if job_number not in [_.split()[0] for _ in msg.split('\n')[2:-1]]:
+
+ if Path(touch_done.replace('&& touch ', '')).exists():
+ num = 666
+ logging.info('cmd={} done! Good for U'.format(cmd_shell))
+ break
+ else:
+ num += 1
+ logging.info('cmd={} shut down!!!trying {} times ...'.format(cmd_shell, num))
+ if num > cls._qsub_re_submit_times:
+ with open(cmd_shell + '.xxx', 'w') as f:
+ f.write('sorry for you, {}!!!\n'.format(cls.user_name))
+ raise Exception('cmd={} failed!!!tried {} times ...'.format(cmd_shell, num))
+
+ @classmethod
+ def cmd(cls, cmd_container, n_jobs: int = '', fn_name='', module_name='', use_qsub=False, nodes=1, ppn=1):
+
+ logging.info(
+ '>-- Dear {}, {}.{} is ready to go. Godspeed!!! --<'.format(cls.user_name, module_name, fn_name))
+ # 解析出cmd_list,函数的返回值等
+ cmd_list, return_value = cls._resolve_cmd(cmd_container)
+
+ n_jobs = int(n_jobs) if n_jobs else len(cmd_list)
+ now = str(datetime.datetime.now().replace(microsecond=0)).replace(' ', '_').replace(':', '-')
+
+ if not use_qsub:
+ if fn_name:
+ _utils.mkdir('cmds_sh')
+ cmd_file = 'cmds_sh/{}_{}.sh'.format(fn_name, now)
+
+ with open(cmd_file, 'w') as f:
+ for cmd in cmd_list:
+ f.write(cmd + '\n')
+ else:
+ fn_name = fn_name if fn_name else 'tmp_qsub_cmd'
+ fn_path = 'cmds_qsub/{}_{}'.format(fn_name, now)
+ _utils.mkdir(fn_path)
+ cmd_qsub_list = []
+
+ for num, cmd in enumerate(cmd_list, start=1):
+ cmd_shell = '{}/{}_{}.pbs'.format(fn_path, fn_name, num)
+ cmd_shell_o = cmd_shell + '.output'
+ cmd_shell_e = cmd_shell + '.error'
+
+ with open(cmd_shell, 'w') as f:
+ touch_done = '&& touch {}.done'.format(cmd_shell)
+ cmd += touch_done
+ f.write('#PBS -l nodes={}:ppn={}\n{}\n'.format(nodes, ppn, cmd))
+
+ # 解决在计算节点投递任务的情况
+
+ cmd_qsub = '{} qsub -V -cwd -o {} -e {} {} "'. \
+ format(cls._qsub_host,
+ cmd_shell_o,
+ cmd_shell_e,
+ cmd_shell)
+ cmd_qsub_list.append((cmd_qsub, touch_done, cmd_shell))
+
+ cmd_list = cmd_qsub_list
+
+ with ThreadPoolExecutor(max_workers=n_jobs) as executor_cmd:
+ event = Event()
+ run_shell = functools.partial(cls._run_shell, use_qsub=use_qsub, event=event)
+
+ # task_list = []
+ # for cmd in cmd_list:
+ # task = executor_cmd.submit(run_shell, cmd)
+ # task_list.append(task)
+ futures = [executor_cmd.submit(run_shell, cmd) for cmd in cmd_list]
+
+ if len(futures) >1:
+
+ done, not_done = wait(futures, return_when=FIRST_EXCEPTION)
+ if len(done) == 1 or len(done) != len(futures):
+ future = list(done)[0]
+ logging.info(future.exception())
+ error_info = f'One task failed with: {future.exception()}, shutting down'
+ for future in futures:
+ future.cancel()
+
+ event.set()
+ raise Exception(error_info)
+
+ # while True:
+ # logging.info(cls.ERROR_LIST)
+ # if len(cls.ERROR_LIST) >= 1:
+ # executor_cmd.shutdown(wait=False)
+
+ # for future in as_completed(task_list):
+ # future.result()
+
+ # try:
+ # wait(task_list)
+ # except ValueError:
+ # print("An error occurs in one of the threads, terminating all threads")
+ # executor_cmd.shutdown(wait=False) # 立即关闭线程
+
+ return return_value
+
+ # def __call__(self, n_jobs: int = '', *args, use_qsub=False, **kwargs):
+ # start = datetime.datetime.now()
+ # cmd_container = self._resolve_cmd(self.fn(*args, **kwargs))
+ # return_value = self.cmd(cmd_container=cmd_container,
+ # n_jobs=n_jobs,
+ # use_qsub=use_qsub,
+ # fn_name=self.fn.__name__,
+ # module_name=self.fn.__module__)
+ #
+ # delta = (datetime.datetime.now() - start).total_seconds()
+ # logging.info('%%%%-- {}.{} took {:.1} min --%%%%'.format(self.fn.__module__, self.fn.__name__, delta / 60))
+ # return return_value
+
+ @classmethod
+ def cmd_wrapper(cls, n_jobs: int = '', use_qsub=False, nodes=1, ppn=1):
+
+ def wrapper(fn):
+ @functools.wraps(fn)
+ def __wrapper(*args, **kwargs):
+ start = datetime.datetime.now()
+ cmd_container = cls._resolve_cmd(fn(*args, **kwargs))
+ return_value = cls.cmd(cmd_container=cmd_container,
+ n_jobs=n_jobs,
+ use_qsub=use_qsub,
+ fn_name=fn.__name__,
+ module_name=inspect.getsourcefile(fn),
+ nodes=nodes, ppn=ppn)
+
+ delta = (datetime.datetime.now() - start).total_seconds()
+ logging.info(
+ '%%%%-- {}.{} took {:.2f} min --%%%%'.format(inspect.getsourcefile(fn), fn.__name__, delta / 60))
+
+ return return_value
+
+ return __wrapper
+
+ return wrapper
+
+
+if __name__ == '__main__':
+ # @CmdRunner.cmd_wrapper()
+ # def foo(a=10):
+ # cmd_list = ['sleep 3 && echo done!' for _ in range(20)]
+ # return cmd_list, a
+ #
+ #
+ # import random
+ #
+ #
+ # @CmdRunner.cmd_wrapper(use_qsub=True, n_jobs=5)
+ # def foo2(a='hello'):
+ # cmd_list = ['sleep {} && echo done!'.format(random.randint(15, 30)) for _ in range(10)]
+ # cmd_list.append('xxxxx ')
+ # return cmd_list, a
+ #
+ #
+ # @CmdRunner.cmd_wrapper(use_qsub=True)
+ # def hello_world(a='hello'):
+ # cmd_list = ['sleep {} && echo done!'.format(random.randint(15, 30)) for _ in range(10)]
+ # cmd_list.append('xxxxx ')
+ # return cmd_list, a
+ #
+ # # @CmdRunner(n_jobs=1) # mdRunner()
+ # # def hello_world2(a='hello'):
+ # # cmd_list = ['sleep {} && echo done!'.format(random.randint(15, 30)) for _ in range(10)]
+ # # cmd_list.append('xxxxx ')
+ # # return cmd_list, a
+
+ @CmdRunner.cmd_wrapper(n_jobs=1)
+ def hello():
+
+ cmd_list = []
+ for i in range(5):
+ cmd = 'echo hello && sleep {}'.format(i)
+ cmd_list.append(cmd)
+
+ return cmd_list
diff --git a/bioinfor_tools/_utils.py b/bioinfor_tools/_utils.py
new file mode 100644
index 0000000..170e962
--- /dev/null
+++ b/bioinfor_tools/_utils.py
@@ -0,0 +1,45 @@
+#!/share/nas2/genome/biosoft/Python//3.7.3/bin/python3
+# -*- coding: utf-8 -*-
+# @Time : 2023/4/28 13:31
+# @Author : jmzhang
+# @Email : jmzhang1911@gmail.com
+from pathlib import Path
+import datetime
+
+
+def mkdir(*path: str):
+ """mkdir recursive-dir"""
+ for p in list(path):
+ if not Path(p).exists():
+ Path(p).mkdir(parents=True, exist_ok=True)
+
+
+def read_cfg(config):
+ with open(config, 'r', encoding='utf-8') as f:
+ config_dict = {}
+ for line in f:
+ if line.strip().startswith('#') or line.strip() == '':
+ continue
+ k, v = line.strip().split()
+ config_dict[k] = str(v).strip()
+ return config_dict
+
+
+def read_yaml(yaml_file):
+ import yaml
+ with open(yaml_file, 'r') as f:
+ yaml_dict = yaml.safe_load(f)
+
+ return yaml_dict
+
+
+def make_summary(script_path, status='doing'):
+ logging_summary = Path(__file__).parent / 'logging_summary.txt'
+ try:
+ with open(logging_summary, 'a') as f:
+ info_log = 'datetime:{}\tpwd:{}\tscript_id:{}\tstatus:{}\n'. \
+ format(datetime.datetime.now().replace(microsecond=0), Path().absolute(), Path(script_path).name,
+ status)
+ f.write(info_log)
+ except PermissionError:
+ pass
diff --git a/bioinfor_tools/logging_summary.txt b/bioinfor_tools/logging_summary.txt
new file mode 100644
index 0000000..a8d5e79
--- /dev/null
+++ b/bioinfor_tools/logging_summary.txt
@@ -0,0 +1,17 @@
+datetime:2023-04-28 09:45:35 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 09:49:37 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 09:51:41 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 09:52:55 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:04:36 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:05:37 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:18:51 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:22:14 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:32:22 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:32:46 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:36:21 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:39:08 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:39:22 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:39:52 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:41:41 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:41:46 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
+datetime:2023-04-28 10:42:09 pwd:/Users/jmzhang/workspace/mygithub/bioinfor_tools script_id:test.py status:done
diff --git a/build/lib/bioinfor_tools/__init__.py b/build/lib/bioinfor_tools/__init__.py
new file mode 100644
index 0000000..620c813
--- /dev/null
+++ b/build/lib/bioinfor_tools/__init__.py
@@ -0,0 +1,19 @@
+#!/share/nas2/genome/biosoft/Python//3.7.3/bin/python3
+# -*- coding: utf-8 -*-
+# @Time : 2023/4/28 09:13
+# @Author : jmzhang
+# @Email : jmzhang1911@gmail.com
+
+import logging
+
+FORMAT = '%(asctime)s %(message)s'
+logging.basicConfig(level=logging.INFO, format=FORMAT, datefmt='%Y-%m-%d %H:%M:%S')
+
+__version__ = 'v0.1 beta'
+
+from ._bio_basic import BioBasic
+from ._cmd_runner import CmdRunner as __CmdRunner
+from ._utils import *
+
+cmd_wrapper = __CmdRunner.cmd_wrapper
+cmd = __CmdRunner.cmd
diff --git a/build/lib/bioinfor_tools/_bio_basic.py b/build/lib/bioinfor_tools/_bio_basic.py
new file mode 100644
index 0000000..228353a
--- /dev/null
+++ b/build/lib/bioinfor_tools/_bio_basic.py
@@ -0,0 +1,20 @@
+from pathlib import Path
+
+
+class BioBasic:
+ """
+ - basic functions and property
+ - read cfg
+ - mkdir dir
+ - module property
+ """
+ # 主路径位置
+ BASE_DIR = Path(__file__).absolute().parent.parent
+ # 日志路径
+ LOGGING_SUMMARY = BASE_DIR / 'logging_summary.txt'
+
+ def __init__(self, module):
+ # 模块所在的绝对父目录
+ self._module_dir = Path(module).absolute().parent
+ # 模块的名称
+ self._module_name = Path(module).name
diff --git a/build/lib/bioinfor_tools/_cmd_runner.py b/build/lib/bioinfor_tools/_cmd_runner.py
new file mode 100644
index 0000000..b52c475
--- /dev/null
+++ b/build/lib/bioinfor_tools/_cmd_runner.py
@@ -0,0 +1,289 @@
+from concurrent.futures import ThreadPoolExecutor, wait, FIRST_EXCEPTION
+import bioinfor_tools._utils as _utils
+from ._bio_basic import BioBasic
+from threading import Event
+from pathlib import Path
+import subprocess
+import functools
+import datetime
+import getpass
+import logging
+import inspect
+import time
+
+
+class CmdRunner(BioBasic):
+ """
+ 1) basic
+ Note: cmd_container: ([cmd1, cmd2, *], *) or [cmd1, cmd2, *]
+ There are two ways to do it:
+ - @CmdRunner.cmd_wrapper(): the wrapper-ed function must return a cmd_container
+ - CmdRunner.runner(cmd_container): just use it as a function
+
+ example 01:
+
+ @CmdRunner.cmd_wrapper()
+ def hello_world():
+ cmd_list = ['sleep 5 && echo done' for _ in range(5)]
+ return cmd_list
+
+ example 02:
+ CmdRunner.runner(['echo hello world'])
+
+ 2) Using PBS: add parameter use_qsub=True
+ 3) outputs:
+ - cmds_sh:
+ - func_name-time.sh # contains cmds
+ - cmds_qsub:
+ - func_name-time
+ - cmd_1.pbs # pbs script
+ - cmd_1.xxx # means failure
+ - cmd_1.output # standard output
+ - cmd_1.error # standard error output
+ - cmd_1.done # means success
+ """
+
+ user_name = getpass.getuser()
+ qsub_nodes = 'hpc12-l-0-0'
+
+ # qsub的一些属性
+ _qsub_host = 'ssh {}@{} "cd {} && '.format(user_name, qsub_nodes, Path().absolute())
+ _qsub_re_submit_times = 2 # 重投次数
+ _qsub_check_time = 60 # 多久检查一次任务执行状况,单位:秒
+
+ subprocess_list = []
+
+ @staticmethod
+ def _resolve_cmd(cmd_container):
+ """
+ 解析cmd -> ([cmd1, cmd2, *], *) or [cmd1, cmd2, *]
+ """
+ if not cmd_container:
+ raise 'None cmd, shut down!!!'
+
+ if isinstance(cmd_container, list):
+ return cmd_container, None
+
+ elif isinstance(cmd_container, tuple) and isinstance(cmd_container[0], list):
+ return cmd_container[0], cmd_container[1:]
+
+ else:
+ raise Exception('please input ([cmd1, cmd2, *], *) or [cmd1, cmd2, *]')
+
+ @classmethod
+ def _run_shell(cls, cmd, use_qsub: bool, event, file_exist_for_skipping=''):
+ """
+ - 执行命令,可选普通shell模式或qsub模式
+ - qsub模式,通过qstat判断任务是否正在进行,运行完成后判断是否touch.done,若失败会重新运行三次
+ """
+ if not use_qsub:
+ logging.info('-> running {}'.format(cmd))
+
+ if event.is_set():
+ logging.info('Stopping, {}'.format(cmd))
+ return
+
+ p = subprocess.Popen(cmd, shell=True)
+ cls.subprocess_list.append(p)
+ # while True:
+ # if event.is_set():
+ # logging.info('Stopping, {}'.format(cmd))
+ # p.terminate()
+
+ ret = p.wait()
+
+ if ret != 0:
+ error_info = '-> `{}` failed:\n{}'.format(cmd, ret)
+ raise Exception(error_info)
+
+ else:
+ cmd_qsub, touch_done, cmd_shell = cmd
+ num = 1
+
+ while num <= cls._qsub_re_submit_times:
+ logging.info('-> qsub is running {}'.format(cmd_shell))
+ p = subprocess.Popen(cmd_qsub, shell=True, stdout=subprocess.PIPE)
+ p.wait()
+ job_number = p.stdout.read().decode().split()[2]
+
+ while True:
+ time.sleep(cls._qsub_check_time)
+ p1 = subprocess.Popen('qstat', shell=True, stdout=subprocess.PIPE)
+ msg = p1.stdout.read().decode()
+
+ if job_number not in [_.split()[0] for _ in msg.split('\n')[2:-1]]:
+
+ if Path(touch_done.replace('&& touch ', '')).exists():
+ num = 666
+ logging.info('cmd={} done! Good for U'.format(cmd_shell))
+ break
+ else:
+ num += 1
+ logging.info('cmd={} shut down!!!trying {} times ...'.format(cmd_shell, num))
+ if num > cls._qsub_re_submit_times:
+ with open(cmd_shell + '.xxx', 'w') as f:
+ f.write('sorry for you, {}!!!\n'.format(cls.user_name))
+ raise Exception('cmd={} failed!!!tried {} times ...'.format(cmd_shell, num))
+
+ @classmethod
+ def cmd(cls, cmd_container, n_jobs: int = '', fn_name='', module_name='', use_qsub=False, nodes=1, ppn=1):
+
+ logging.info(
+ '>-- Dear {}, {}.{} is ready to go. Godspeed!!! --<'.format(cls.user_name, module_name, fn_name))
+ # 解析出cmd_list,函数的返回值等
+ cmd_list, return_value = cls._resolve_cmd(cmd_container)
+
+ n_jobs = int(n_jobs) if n_jobs else len(cmd_list)
+ now = str(datetime.datetime.now().replace(microsecond=0)).replace(' ', '_').replace(':', '-')
+
+ if not use_qsub:
+ if fn_name:
+ _utils.mkdir('cmds_sh')
+ cmd_file = 'cmds_sh/{}_{}.sh'.format(fn_name, now)
+
+ with open(cmd_file, 'w') as f:
+ for cmd in cmd_list:
+ f.write(cmd + '\n')
+ else:
+ fn_name = fn_name if fn_name else 'tmp_qsub_cmd'
+ fn_path = 'cmds_qsub/{}_{}'.format(fn_name, now)
+ _utils.mkdir(fn_path)
+ cmd_qsub_list = []
+
+ for num, cmd in enumerate(cmd_list, start=1):
+ cmd_shell = '{}/{}_{}.pbs'.format(fn_path, fn_name, num)
+ cmd_shell_o = cmd_shell + '.output'
+ cmd_shell_e = cmd_shell + '.error'
+
+ with open(cmd_shell, 'w') as f:
+ touch_done = '&& touch {}.done'.format(cmd_shell)
+ cmd += touch_done
+ f.write('#PBS -l nodes={}:ppn={}\n{}\n'.format(nodes, ppn, cmd))
+
+ # 解决在计算节点投递任务的情况
+
+ cmd_qsub = '{} qsub -V -cwd -o {} -e {} {} "'. \
+ format(cls._qsub_host,
+ cmd_shell_o,
+ cmd_shell_e,
+ cmd_shell)
+ cmd_qsub_list.append((cmd_qsub, touch_done, cmd_shell))
+
+ cmd_list = cmd_qsub_list
+
+ with ThreadPoolExecutor(max_workers=n_jobs) as executor_cmd:
+ event = Event()
+ run_shell = functools.partial(cls._run_shell, use_qsub=use_qsub, event=event)
+
+ # task_list = []
+ # for cmd in cmd_list:
+ # task = executor_cmd.submit(run_shell, cmd)
+ # task_list.append(task)
+ futures = [executor_cmd.submit(run_shell, cmd) for cmd in cmd_list]
+
+ if len(futures) >1:
+
+ done, not_done = wait(futures, return_when=FIRST_EXCEPTION)
+ if len(done) == 1 or len(done) != len(futures):
+ future = list(done)[0]
+ logging.info(future.exception())
+ error_info = f'One task failed with: {future.exception()}, shutting down'
+ for future in futures:
+ future.cancel()
+
+ event.set()
+ raise Exception(error_info)
+
+ # while True:
+ # logging.info(cls.ERROR_LIST)
+ # if len(cls.ERROR_LIST) >= 1:
+ # executor_cmd.shutdown(wait=False)
+
+ # for future in as_completed(task_list):
+ # future.result()
+
+ # try:
+ # wait(task_list)
+ # except ValueError:
+ # print("An error occurs in one of the threads, terminating all threads")
+ # executor_cmd.shutdown(wait=False) # 立即关闭线程
+
+ return return_value
+
+ # def __call__(self, n_jobs: int = '', *args, use_qsub=False, **kwargs):
+ # start = datetime.datetime.now()
+ # cmd_container = self._resolve_cmd(self.fn(*args, **kwargs))
+ # return_value = self.cmd(cmd_container=cmd_container,
+ # n_jobs=n_jobs,
+ # use_qsub=use_qsub,
+ # fn_name=self.fn.__name__,
+ # module_name=self.fn.__module__)
+ #
+ # delta = (datetime.datetime.now() - start).total_seconds()
+ # logging.info('%%%%-- {}.{} took {:.1} min --%%%%'.format(self.fn.__module__, self.fn.__name__, delta / 60))
+ # return return_value
+
+ @classmethod
+ def cmd_wrapper(cls, n_jobs: int = '', use_qsub=False, nodes=1, ppn=1):
+
+ def wrapper(fn):
+ @functools.wraps(fn)
+ def __wrapper(*args, **kwargs):
+ start = datetime.datetime.now()
+ cmd_container = cls._resolve_cmd(fn(*args, **kwargs))
+ return_value = cls.cmd(cmd_container=cmd_container,
+ n_jobs=n_jobs,
+ use_qsub=use_qsub,
+ fn_name=fn.__name__,
+ module_name=inspect.getsourcefile(fn),
+ nodes=nodes, ppn=ppn)
+
+ delta = (datetime.datetime.now() - start).total_seconds()
+ logging.info(
+ '%%%%-- {}.{} took {:.2f} min --%%%%'.format(inspect.getsourcefile(fn), fn.__name__, delta / 60))
+
+ return return_value
+
+ return __wrapper
+
+ return wrapper
+
+
+if __name__ == '__main__':
+ # @CmdRunner.cmd_wrapper()
+ # def foo(a=10):
+ # cmd_list = ['sleep 3 && echo done!' for _ in range(20)]
+ # return cmd_list, a
+ #
+ #
+ # import random
+ #
+ #
+ # @CmdRunner.cmd_wrapper(use_qsub=True, n_jobs=5)
+ # def foo2(a='hello'):
+ # cmd_list = ['sleep {} && echo done!'.format(random.randint(15, 30)) for _ in range(10)]
+ # cmd_list.append('xxxxx ')
+ # return cmd_list, a
+ #
+ #
+ # @CmdRunner.cmd_wrapper(use_qsub=True)
+ # def hello_world(a='hello'):
+ # cmd_list = ['sleep {} && echo done!'.format(random.randint(15, 30)) for _ in range(10)]
+ # cmd_list.append('xxxxx ')
+ # return cmd_list, a
+ #
+ # # @CmdRunner(n_jobs=1) # mdRunner()
+ # # def hello_world2(a='hello'):
+ # # cmd_list = ['sleep {} && echo done!'.format(random.randint(15, 30)) for _ in range(10)]
+ # # cmd_list.append('xxxxx ')
+ # # return cmd_list, a
+
+ @CmdRunner.cmd_wrapper(n_jobs=1)
+ def hello():
+
+ cmd_list = []
+ for i in range(5):
+ cmd = 'echo hello && sleep {}'.format(i)
+ cmd_list.append(cmd)
+
+ return cmd_list
diff --git a/build/lib/bioinfor_tools/_utils.py b/build/lib/bioinfor_tools/_utils.py
new file mode 100644
index 0000000..170e962
--- /dev/null
+++ b/build/lib/bioinfor_tools/_utils.py
@@ -0,0 +1,45 @@
+#!/share/nas2/genome/biosoft/Python//3.7.3/bin/python3
+# -*- coding: utf-8 -*-
+# @Time : 2023/4/28 13:31
+# @Author : jmzhang
+# @Email : jmzhang1911@gmail.com
+from pathlib import Path
+import datetime
+
+
+def mkdir(*path: str):
+ """mkdir recursive-dir"""
+ for p in list(path):
+ if not Path(p).exists():
+ Path(p).mkdir(parents=True, exist_ok=True)
+
+
+def read_cfg(config):
+ with open(config, 'r', encoding='utf-8') as f:
+ config_dict = {}
+ for line in f:
+ if line.strip().startswith('#') or line.strip() == '':
+ continue
+ k, v = line.strip().split()
+ config_dict[k] = str(v).strip()
+ return config_dict
+
+
+def read_yaml(yaml_file):
+ import yaml
+ with open(yaml_file, 'r') as f:
+ yaml_dict = yaml.safe_load(f)
+
+ return yaml_dict
+
+
+def make_summary(script_path, status='doing'):
+ logging_summary = Path(__file__).parent / 'logging_summary.txt'
+ try:
+ with open(logging_summary, 'a') as f:
+ info_log = 'datetime:{}\tpwd:{}\tscript_id:{}\tstatus:{}\n'. \
+ format(datetime.datetime.now().replace(microsecond=0), Path().absolute(), Path(script_path).name,
+ status)
+ f.write(info_log)
+ except PermissionError:
+ pass
diff --git a/cmds_sh/foo_2023-04-28_09-29-49.sh b/cmds_sh/foo_2023-04-28_09-29-49.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-29-49.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-29-58.sh b/cmds_sh/foo_2023-04-28_09-29-58.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-29-58.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-31-29.sh b/cmds_sh/foo_2023-04-28_09-31-29.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-31-29.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-41-01.sh b/cmds_sh/foo_2023-04-28_09-41-01.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-41-01.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-43-54.sh b/cmds_sh/foo_2023-04-28_09-43-54.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-43-54.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-45-00.sh b/cmds_sh/foo_2023-04-28_09-45-00.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-45-00.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-45-29.sh b/cmds_sh/foo_2023-04-28_09-45-29.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-45-29.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-49-31.sh b/cmds_sh/foo_2023-04-28_09-49-31.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-49-31.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-51-35.sh b/cmds_sh/foo_2023-04-28_09-51-35.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-51-35.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-52-49.sh b/cmds_sh/foo_2023-04-28_09-52-49.sh
new file mode 100644
index 0000000..4f73a9a
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-52-49.sh
@@ -0,0 +1,5 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_09-54-39.sh b/cmds_sh/foo_2023-04-28_09-54-39.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_09-54-39.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-04-30.sh b/cmds_sh/foo_2023-04-28_10-04-30.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-04-30.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-05-31.sh b/cmds_sh/foo_2023-04-28_10-05-31.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-05-31.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-08-44.sh b/cmds_sh/foo_2023-04-28_10-08-44.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-08-44.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-09-05.sh b/cmds_sh/foo_2023-04-28_10-09-05.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-09-05.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-11-13.sh b/cmds_sh/foo_2023-04-28_10-11-13.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-11-13.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-11-34.sh b/cmds_sh/foo_2023-04-28_10-11-34.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-11-34.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-15-29.sh b/cmds_sh/foo_2023-04-28_10-15-29.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-15-29.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-16-08.sh b/cmds_sh/foo_2023-04-28_10-16-08.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-16-08.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-17-09.sh b/cmds_sh/foo_2023-04-28_10-17-09.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-17-09.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-18-45.sh b/cmds_sh/foo_2023-04-28_10-18-45.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-18-45.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-22-08.sh b/cmds_sh/foo_2023-04-28_10-22-08.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-22-08.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-24-49.sh b/cmds_sh/foo_2023-04-28_10-24-49.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-24-49.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-32-16.sh b/cmds_sh/foo_2023-04-28_10-32-16.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-32-16.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-32-40.sh b/cmds_sh/foo_2023-04-28_10-32-40.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-32-40.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-36-19.sh b/cmds_sh/foo_2023-04-28_10-36-19.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-36-19.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-39-02.sh b/cmds_sh/foo_2023-04-28_10-39-02.sh
new file mode 100644
index 0000000..4532b83
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-39-02.sh
@@ -0,0 +1,6 @@
+sleep 0
+sleep 1
+xxx
+sleep 2
+sleep 3
+sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-39-16.sh b/cmds_sh/foo_2023-04-28_10-39-16.sh
new file mode 100644
index 0000000..4532b83
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-39-16.sh
@@ -0,0 +1,6 @@
+sleep 0
+sleep 1
+xxx
+sleep 2
+sleep 3
+sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-39-46.sh b/cmds_sh/foo_2023-04-28_10-39-46.sh
new file mode 100644
index 0000000..4532b83
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-39-46.sh
@@ -0,0 +1,6 @@
+sleep 0
+sleep 1
+xxx
+sleep 2
+sleep 3
+sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-41-35.sh b/cmds_sh/foo_2023-04-28_10-41-35.sh
new file mode 100644
index 0000000..4532b83
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-41-35.sh
@@ -0,0 +1,6 @@
+sleep 0
+sleep 1
+xxx
+sleep 2
+sleep 3
+sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-41-44.sh b/cmds_sh/foo_2023-04-28_10-41-44.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-41-44.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-42-07.sh b/cmds_sh/foo_2023-04-28_10-42-07.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-42-07.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-42-45.sh b/cmds_sh/foo_2023-04-28_10-42-45.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-42-45.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-42-56.sh b/cmds_sh/foo_2023-04-28_10-42-56.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-42-56.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-43-11.sh b/cmds_sh/foo_2023-04-28_10-43-11.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-43-11.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-43-24.sh b/cmds_sh/foo_2023-04-28_10-43-24.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-43-24.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-45-23.sh b/cmds_sh/foo_2023-04-28_10-45-23.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-45-23.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-45-46.sh b/cmds_sh/foo_2023-04-28_10-45-46.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-45-46.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-46-38.sh b/cmds_sh/foo_2023-04-28_10-46-38.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-46-38.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-46-50.sh b/cmds_sh/foo_2023-04-28_10-46-50.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-46-50.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-46-58.sh b/cmds_sh/foo_2023-04-28_10-46-58.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-46-58.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-47-02.sh b/cmds_sh/foo_2023-04-28_10-47-02.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-47-02.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-47-10.sh b/cmds_sh/foo_2023-04-28_10-47-10.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-47-10.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-47-26.sh b/cmds_sh/foo_2023-04-28_10-47-26.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-47-26.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-47-35.sh b/cmds_sh/foo_2023-04-28_10-47-35.sh
new file mode 100644
index 0000000..24b1a96
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-47-35.sh
@@ -0,0 +1,6 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
diff --git a/cmds_sh/foo_2023-04-28_10-47-49.sh b/cmds_sh/foo_2023-04-28_10-47-49.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-47-49.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-48-16.sh b/cmds_sh/foo_2023-04-28_10-48-16.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-48-16.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-48-29.sh b/cmds_sh/foo_2023-04-28_10-48-29.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-48-29.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-48-59.sh b/cmds_sh/foo_2023-04-28_10-48-59.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-48-59.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-49-25.sh b/cmds_sh/foo_2023-04-28_10-49-25.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-49-25.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-49-32.sh b/cmds_sh/foo_2023-04-28_10-49-32.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-49-32.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-50-42.sh b/cmds_sh/foo_2023-04-28_10-50-42.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-50-42.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-52-32.sh b/cmds_sh/foo_2023-04-28_10-52-32.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-52-32.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-52-34.sh b/cmds_sh/foo_2023-04-28_10-52-34.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-52-34.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-58-04.sh b/cmds_sh/foo_2023-04-28_10-58-04.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-58-04.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-58-09.sh b/cmds_sh/foo_2023-04-28_10-58-09.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-58-09.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-58-15.sh b/cmds_sh/foo_2023-04-28_10-58-15.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-58-15.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-59-04.sh b/cmds_sh/foo_2023-04-28_10-59-04.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-59-04.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-59-30.sh b/cmds_sh/foo_2023-04-28_10-59-30.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-59-30.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_10-59-56.sh b/cmds_sh/foo_2023-04-28_10-59-56.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_10-59-56.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-00-01.sh b/cmds_sh/foo_2023-04-28_11-00-01.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-00-01.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-00-47.sh b/cmds_sh/foo_2023-04-28_11-00-47.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-00-47.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-01-01.sh b/cmds_sh/foo_2023-04-28_11-01-01.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-01-01.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-01-04.sh b/cmds_sh/foo_2023-04-28_11-01-04.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-01-04.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-01-11.sh b/cmds_sh/foo_2023-04-28_11-01-11.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-01-11.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-01-16.sh b/cmds_sh/foo_2023-04-28_11-01-16.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-01-16.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-01-18.sh b/cmds_sh/foo_2023-04-28_11-01-18.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-01-18.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-02-25.sh b/cmds_sh/foo_2023-04-28_11-02-25.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-02-25.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-02-27.sh b/cmds_sh/foo_2023-04-28_11-02-27.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-02-27.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-02-32.sh b/cmds_sh/foo_2023-04-28_11-02-32.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-02-32.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-02-36.sh b/cmds_sh/foo_2023-04-28_11-02-36.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-02-36.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-02-40.sh b/cmds_sh/foo_2023-04-28_11-02-40.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-02-40.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-02-45.sh b/cmds_sh/foo_2023-04-28_11-02-45.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-02-45.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-02-50.sh b/cmds_sh/foo_2023-04-28_11-02-50.sh
new file mode 100644
index 0000000..2dbcd57
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-02-50.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+xxx
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-03-53.sh b/cmds_sh/foo_2023-04-28_11-03-53.sh
new file mode 100644
index 0000000..e731b6b
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-03-53.sh
@@ -0,0 +1,11 @@
+xxx
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-03-56.sh b/cmds_sh/foo_2023-04-28_11-03-56.sh
new file mode 100644
index 0000000..e731b6b
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-03-56.sh
@@ -0,0 +1,11 @@
+xxx
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-04-05.sh b/cmds_sh/foo_2023-04-28_11-04-05.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-04-05.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-08-23.sh b/cmds_sh/foo_2023-04-28_11-08-23.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-08-23.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-08-31.sh b/cmds_sh/foo_2023-04-28_11-08-31.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-08-31.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-09-00.sh b/cmds_sh/foo_2023-04-28_11-09-00.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-09-00.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-10-02.sh b/cmds_sh/foo_2023-04-28_11-10-02.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-10-02.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-10-08.sh b/cmds_sh/foo_2023-04-28_11-10-08.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-10-08.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-10-58.sh b/cmds_sh/foo_2023-04-28_11-10-58.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-10-58.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-11-23.sh b/cmds_sh/foo_2023-04-28_11-11-23.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-11-23.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-12-06.sh b/cmds_sh/foo_2023-04-28_11-12-06.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-12-06.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-15-01.sh b/cmds_sh/foo_2023-04-28_11-15-01.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-15-01.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-15-19.sh b/cmds_sh/foo_2023-04-28_11-15-19.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-15-19.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-17-28.sh b/cmds_sh/foo_2023-04-28_11-17-28.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-17-28.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-18-17.sh b/cmds_sh/foo_2023-04-28_11-18-17.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-18-17.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-18-57.sh b/cmds_sh/foo_2023-04-28_11-18-57.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-18-57.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-19-55.sh b/cmds_sh/foo_2023-04-28_11-19-55.sh
new file mode 100644
index 0000000..eabf661
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-19-55.sh
@@ -0,0 +1,10 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-20-26.sh b/cmds_sh/foo_2023-04-28_11-20-26.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-20-26.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-20-41.sh b/cmds_sh/foo_2023-04-28_11-20-41.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-20-41.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-20-53.sh b/cmds_sh/foo_2023-04-28_11-20-53.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-20-53.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-21-02.sh b/cmds_sh/foo_2023-04-28_11-21-02.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-21-02.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-22-19.sh b/cmds_sh/foo_2023-04-28_11-22-19.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-22-19.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-22-52.sh b/cmds_sh/foo_2023-04-28_11-22-52.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-22-52.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-25-31.sh b/cmds_sh/foo_2023-04-28_11-25-31.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-25-31.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-25-54.sh b/cmds_sh/foo_2023-04-28_11-25-54.sh
new file mode 100644
index 0000000..5bb676c
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-25-54.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 5
+xxx
+echo 1 && sleep 5
+echo 2 && sleep 5
+echo 3 && sleep 5
+echo 4 && sleep 5
+echo 5 && sleep 5
+echo 6 && sleep 5
+echo 7 && sleep 5
+echo 8 && sleep 5
+echo 9 && sleep 5
diff --git a/cmds_sh/foo_2023-04-28_11-28-04.sh b/cmds_sh/foo_2023-04-28_11-28-04.sh
new file mode 100644
index 0000000..5bb676c
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-28-04.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 5
+xxx
+echo 1 && sleep 5
+echo 2 && sleep 5
+echo 3 && sleep 5
+echo 4 && sleep 5
+echo 5 && sleep 5
+echo 6 && sleep 5
+echo 7 && sleep 5
+echo 8 && sleep 5
+echo 9 && sleep 5
diff --git a/cmds_sh/foo_2023-04-28_11-28-19.sh b/cmds_sh/foo_2023-04-28_11-28-19.sh
new file mode 100644
index 0000000..5bb676c
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-28-19.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 5
+xxx
+echo 1 && sleep 5
+echo 2 && sleep 5
+echo 3 && sleep 5
+echo 4 && sleep 5
+echo 5 && sleep 5
+echo 6 && sleep 5
+echo 7 && sleep 5
+echo 8 && sleep 5
+echo 9 && sleep 5
diff --git a/cmds_sh/foo_2023-04-28_11-28-23.sh b/cmds_sh/foo_2023-04-28_11-28-23.sh
new file mode 100644
index 0000000..5bb676c
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-28-23.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 5
+xxx
+echo 1 && sleep 5
+echo 2 && sleep 5
+echo 3 && sleep 5
+echo 4 && sleep 5
+echo 5 && sleep 5
+echo 6 && sleep 5
+echo 7 && sleep 5
+echo 8 && sleep 5
+echo 9 && sleep 5
diff --git a/cmds_sh/foo_2023-04-28_11-28-29.sh b/cmds_sh/foo_2023-04-28_11-28-29.sh
new file mode 100644
index 0000000..5bb676c
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-28-29.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 5
+xxx
+echo 1 && sleep 5
+echo 2 && sleep 5
+echo 3 && sleep 5
+echo 4 && sleep 5
+echo 5 && sleep 5
+echo 6 && sleep 5
+echo 7 && sleep 5
+echo 8 && sleep 5
+echo 9 && sleep 5
diff --git a/cmds_sh/foo_2023-04-28_11-28-34.sh b/cmds_sh/foo_2023-04-28_11-28-34.sh
new file mode 100644
index 0000000..5bb676c
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-28-34.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 5
+xxx
+echo 1 && sleep 5
+echo 2 && sleep 5
+echo 3 && sleep 5
+echo 4 && sleep 5
+echo 5 && sleep 5
+echo 6 && sleep 5
+echo 7 && sleep 5
+echo 8 && sleep 5
+echo 9 && sleep 5
diff --git a/cmds_sh/foo_2023-04-28_11-28-56.sh b/cmds_sh/foo_2023-04-28_11-28-56.sh
new file mode 100644
index 0000000..c356651
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-28-56.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep i
+xxx
+echo 1 && sleep i
+echo 2 && sleep i
+echo 3 && sleep i
+echo 4 && sleep i
+echo 5 && sleep i
+echo 6 && sleep i
+echo 7 && sleep i
+echo 8 && sleep i
+echo 9 && sleep i
diff --git a/cmds_sh/foo_2023-04-28_11-29-10.sh b/cmds_sh/foo_2023-04-28_11-29-10.sh
new file mode 100644
index 0000000..992b4e2
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-29-10.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+xxx
+echo 1 && sleep 1
+echo 2 && sleep 2
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-29-19.sh b/cmds_sh/foo_2023-04-28_11-29-19.sh
new file mode 100644
index 0000000..21aa758
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-29-19.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+xxx
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-29-45.sh b/cmds_sh/foo_2023-04-28_11-29-45.sh
new file mode 100644
index 0000000..21aa758
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-29-45.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+xxx
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-31-18.sh b/cmds_sh/foo_2023-04-28_11-31-18.sh
new file mode 100644
index 0000000..21aa758
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-31-18.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+xxx
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-31-27.sh b/cmds_sh/foo_2023-04-28_11-31-27.sh
new file mode 100644
index 0000000..21aa758
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-31-27.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 0
+echo 1 && sleep 1
+echo 2 && sleep 2
+xxx
+echo 3 && sleep 3
+echo 4 && sleep 4
+echo 5 && sleep 5
+echo 6 && sleep 6
+echo 7 && sleep 7
+echo 8 && sleep 8
+echo 9 && sleep 9
diff --git a/cmds_sh/foo_2023-04-28_11-31-41.sh b/cmds_sh/foo_2023-04-28_11-31-41.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-31-41.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_11-39-24.sh b/cmds_sh/foo_2023-04-28_11-39-24.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-39-24.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_11-40-55.sh b/cmds_sh/foo_2023-04-28_11-40-55.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-40-55.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_11-44-36.sh b/cmds_sh/foo_2023-04-28_11-44-36.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-44-36.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_11-45-14.sh b/cmds_sh/foo_2023-04-28_11-45-14.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-45-14.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_11-45-27.sh b/cmds_sh/foo_2023-04-28_11-45-27.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-45-27.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_11-45-56.sh b/cmds_sh/foo_2023-04-28_11-45-56.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-45-56.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_11-47-41.sh b/cmds_sh/foo_2023-04-28_11-47-41.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-47-41.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_11-48-14.sh b/cmds_sh/foo_2023-04-28_11-48-14.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_11-48-14.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_13-23-42.sh b/cmds_sh/foo_2023-04-28_13-23-42.sh
new file mode 100644
index 0000000..e6b58dd
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_13-23-42.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 60
+echo 1 && sleep 60
+echo 2 && sleep 60
+xxx
+echo 3 && sleep 60
+echo 4 && sleep 60
+echo 5 && sleep 60
+echo 6 && sleep 60
+echo 7 && sleep 60
+echo 8 && sleep 60
+echo 9 && sleep 60
diff --git a/cmds_sh/foo_2023-04-28_13-28-07.sh b/cmds_sh/foo_2023-04-28_13-28-07.sh
new file mode 100644
index 0000000..c258eaa
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_13-28-07.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 6
+echo 1 && sleep 6
+echo 2 && sleep 6
+xxx
+echo 3 && sleep 6
+echo 4 && sleep 6
+echo 5 && sleep 6
+echo 6 && sleep 6
+echo 7 && sleep 6
+echo 8 && sleep 6
+echo 9 && sleep 6
diff --git a/cmds_sh/foo_2023-04-28_14-19-31.sh b/cmds_sh/foo_2023-04-28_14-19-31.sh
new file mode 100644
index 0000000..c258eaa
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_14-19-31.sh
@@ -0,0 +1,11 @@
+echo 0 && sleep 6
+echo 1 && sleep 6
+echo 2 && sleep 6
+xxx
+echo 3 && sleep 6
+echo 4 && sleep 6
+echo 5 && sleep 6
+echo 6 && sleep 6
+echo 7 && sleep 6
+echo 8 && sleep 6
+echo 9 && sleep 6
diff --git a/cmds_sh/foo_2023-04-28_14-20-01.sh b/cmds_sh/foo_2023-04-28_14-20-01.sh
new file mode 100644
index 0000000..86cf64f
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_14-20-01.sh
@@ -0,0 +1,10 @@
+echo 0 && sleep 6
+echo 1 && sleep 6
+echo 2 && sleep 6
+echo 3 && sleep 6
+echo 4 && sleep 6
+echo 5 && sleep 6
+echo 6 && sleep 6
+echo 7 && sleep 6
+echo 8 && sleep 6
+echo 9 && sleep 6
diff --git a/cmds_sh/foo_2023-04-28_14-40-44.sh b/cmds_sh/foo_2023-04-28_14-40-44.sh
new file mode 100644
index 0000000..86cf64f
--- /dev/null
+++ b/cmds_sh/foo_2023-04-28_14-40-44.sh
@@ -0,0 +1,10 @@
+echo 0 && sleep 6
+echo 1 && sleep 6
+echo 2 && sleep 6
+echo 3 && sleep 6
+echo 4 && sleep 6
+echo 5 && sleep 6
+echo 6 && sleep 6
+echo 7 && sleep 6
+echo 8 && sleep 6
+echo 9 && sleep 6
diff --git a/dist/bioinfor_tools-0.1-py3-none-any.whl b/dist/bioinfor_tools-0.1-py3-none-any.whl
new file mode 100644
index 0000000..7e53ced
Binary files /dev/null and b/dist/bioinfor_tools-0.1-py3-none-any.whl differ
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..d24a2d9
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,12 @@
+from setuptools import setup
+
+setup(
+ name='bioinfor_tools',
+ version='v0.1',
+ packages=['bioinfor_tools'],
+ url='',
+ license='',
+ author='jmzhang',
+ author_email='jmzhang1911@gmail.com',
+ description=''
+)
diff --git a/test.py b/test.py
new file mode 100644
index 0000000..2cd7463
--- /dev/null
+++ b/test.py
@@ -0,0 +1,78 @@
+#!/share/nas2/genome/biosoft/Python//3.7.3/bin/python3
+# -*- coding: utf-8 -*-
+# @Time : 2023/4/28 09:16
+# @Author : jmzhang
+# @Email : jmzhang1911@gmail.com
+import logging
+
+import bioinfor_tools as bt
+from bioinfor_tools._bio_basic import BioBasic
+
+
+@bt.cmd_wrapper(n_jobs=5)
+def foo():
+ cmd = list()
+ for i in range(10):
+ cmd.append('echo {} && sleep 6'.format(i, i))
+
+ #cmd.insert(3, 'xxx')
+ logging.info(cmd)
+ return cmd, 'hello'
+
+
+class B(bt.BioBasic):
+ pass
+
+
+bt.cmd(['sleep 2 && echo done'])
+bt.cmd(['sleep 3 && echo done'])
+foo()
+
+# foo()
+# print('done')
+
+# SuperFastPython.com
+# example of stopping all running tasks when one task fails
+from time import sleep
+from threading import Event
+from concurrent.futures import ThreadPoolExecutor
+from concurrent.futures import wait
+from concurrent.futures import FIRST_EXCEPTION
+
+
+# mock target task function
+def work(event, name):
+ # pretend read data for a long time
+ for _ in range(10):
+ # pretend to read some data
+ sleep(3)
+ # check if this task should fail
+ if name == 6:
+ print(f'Task has failed, name={name}')
+ raise Exception('Something bad happened')
+ # check if the task should stop
+ if event.is_set():
+ print(f'Stopping, name={name}')
+ return
+
+# create an event used to stop running tasks
+# event = Event()
+# # create a thread pool
+# with ThreadPoolExecutor(5) as executor:
+# # execute many tasks
+# futures = [executor.submit(work, event, i) for i in range(10)]
+# # wait for all tasks to complete, or one task to fail
+# print('Waiting for tasks to complete, or fail...')
+# done, not_done = wait(futures, return_when=FIRST_EXCEPTION)
+# # check if not all tasks are done
+# if len(done) > 0 and len(done) != len(futures):
+# # check if an exception was raised
+# future = done.pop()
+# if future.exception() != None:
+# print(f'One task failed with: {future.exception()}, shutting down')
+# # cancel any scheduled tasks
+# for future in futures:
+# future.cancel()
+# # stop all running tasks
+# event.set()
+# print('All done.')