find and sed string in docker got error ` Device or resource busy`

Yes, as you found, the file is mounted by docker, which means you are not allowed to change its inode from within docker container. But, what if you only change the content of file without touching its inode, does it work? Sure, it does. So all you need to do is to find a way to change the content of original file only, rather than create a new file and then replace the original one.

Command sed with option -i does create new file, and then replace the old file with the new one, which definitely will change the file inode. That is why it gives you the error.

So, which ways can change the content of file? Many many ways.

  1. shell redirect, e.g., echo abc > file
  2. command cp, e.g., cp new old
  3. vim
  4. ed

Give you several examples for how to fix your issue:

The cp way:

find ${BASIN_SPIDER_CONFIG_PATH} -type f -name "*.json" | xargs -L1 bash -c 'sed "s/" $1 > /tmp/.intermediate-file-2431; cp /tmp/.intermediate-file-2431 $1;' --

The vim way

cat > /tmp/vim-temp-script <<EOF
:set nobackup backupcopy=yes
:let i = 0
:while 1
:  let i += 1
:  %s/
:  if i >= argc()
:    break
:  endif
:  wn
find ${BASIN_SPIDER_CONFIG_PATH} -type f -name "*.json" | xargs vim -s /tmp/vim-temp-script

The ed way

find ${BASIN_SPIDER_CONFIG_PATH} -type f -name "*.json"|xargs -L1 bash -c 'ed $1 <<EOF
EOF' --

sed has a -c option to use with -i so that it does copy instead of move, which makes this work.

This works:

RUN sed -ci "s/localhost/foobar/g" /etc/hosts

Note carefully, however, that sed -ic won't work, as it would make a backup file ending in .c, rather than doing what sed -i -c or sed -ci does.

Cleaned up a docker script today from this learning :)