Основная проблема (вызывающая синтаксическую ошибку) заключается в строке sed
:
sed -n '$j,4800p' IM_DlCtrlRef.txt >> IM_DlCtrlRef_bak
Вы хотите использовать переменную оболочки $ j
в своем сценарии sed
в качестве номера начальной строки (сценарий sed
извлекает строки $ j
до 4800 вне файла), но вы не позволяете оболочке расширять переменную, используя одинарные кавычки. Это означает, что sed
получит $ j
в качестве начального адреса, что не приведет к путанице.
Просто измените эту строку, чтобы вместо нее были двойные кавычки.
Теперь посмотрим на полный сценарий:
LINEnum=$(grep -nr "#32" IM_DlCtrlRef.txt | cut -d : -f 1)
for j in $LINEnum
do
echo $j
sed -n "$j,4800p" IM_DlCtrlRef.txt >> IM_DlCtrlRef_bak
for insertl in {1..4}
do
cat zero.txt >> IM_DlCtrlRef_bak
done
done
Здесь есть несколько проблем со стилем и производительностью, которые вы можете или не захотите исправлять.
Во-первых, вы считываете все номера строк в переменную. Это напрасная трата памяти, но вам необходимо это сделать, потому что цикл for
должен точно знать, что следует выполнить в цикле.
Другим решением было бы считывать номера строк один за другим:
grep -nr "#32" IM_DlCtrlRef.txt | cut -d : -f 1 |
while read j; do
# ...
done
Это означает, что нет ограничений на количество данных, которые скрипт может проглотить.
Кстати, -r
делает grep
выполняет рекурсивный поиск, поэтому, вероятно, здесь это не нужно. Замените его на -F
, поскольку вы ищете фиксированную строку (а не регулярное выражение).
Однако, поскольку вас интересуют только номера строк, совпадающих с # 32
, вы можете заменить весь этот канал на
sed -n '/#32/=' IM_DlCtrlRef.txt
Команда sed
=
печатает номера строк.
После последнего раунда доработки сценарий становится
sed -n '/#32/=' IM_DlCtrlRef.txt |
while read j; do
echo $j
sed -n "$j,4800p" IM_DlCtrlRef.txt >>IM_DlCtrlRef_bak
for insertl in {1..4}; do
cat zero.txt >>IM_DlCtrlRef_bak
done
done
У нас была такая же проблема: сервер должен разрешить scp sftp и rsync для всех пользователей, но нет соединения с командной строкой. База данных пользователей находится в ldap, и мы не можем изменить /etc/passwd локально. Поэтому rssh был не вариант.
Одно из решений, которое я нашел, это использование ForceCommand
и сценария оболочки.
В /etc/ssh/sshd_config добавляются следующие строки:
Match user *
X11Forwarding no
AllowTcpForwarding no
ForceCommand /usr/local/bin/wrapper-shell user1 user2 user3
Где userX
- специальные пользователи, которым разрешено входить в систему через ssh.
Сценарий обертки-оболочки, который выполняет фактическую фильтрацию, следующий:
#!/bin/sh
SSHCMD=`echo "$SSH_ORIGINAL_COMMAND" | awk '{ print $1 }'`
ME=`id -u -n`
DOIT=Maybe
# Root is always allowed in order to not being locked out
for n in root $*
do
if [ "$ME" = "$n" ]
then
DOIT=YES
break
fi
done
if [ "$DOIT" = YES -o "$SSHCMD" = "scp" -o "$SSHCMD" = "rsync" -o "$SSHCMD" = /usr/lib/openssh/sftp-server ]
then
sh -c "$SSH_ORIGINAL_COMMAND"
else
cat <<EOF 1>&2
This account is restricted and the command is not allowed.
User $ME is locked out.
If you believe this is in error, please contact your system administrator.
EOF
exit 1
fi