Ubuntu 22.04搭建OpenStreeMap地址解析服务(保姆级教程)
1.数据准备
1.1.全球数据
下载地址:https://planet.openstreetmap.org/
1.2.特定区域的数据
下载地址:Geofabrik Download Server
2.安装必要的软件包
2.1.更新系统软件包
sudo apt updatesudo apt upgrade
2.2.安装所需要的软件包
执行下面的命令,一步安装所需要的配套软件。
sudo apt install -y build-essential cmake g++ libboost-dev libboost-system-dev \libboost-filesystem-dev libexpat1-dev zlib1g-dev \libbz2-dev libpq-dev liblua5.3-dev lua5.3 lua-dkjson \nlohmann-json3-dev postgresql-14-postgis-3 \postgresql-contrib-14 postgresql-14-postgis-3-scripts \php-cli php-pgsql php-intl libicu-dev python3-dotenv \python3-psycopg2 python3-psutil python3-jinja2 \python3-icu python3-datrie python3-sqlalchemy \python3-asyncpg python3-yaml git
3.配置postgresql
3.1. 切换到 postgres 用户
在 Linux 系统中,默认安装 PostgreSQL 后会创建一个名为 postgres
的系统用户,你可以使用以下命令切换到该用户:
sudo su - postgres
执行此命令后,你将进入 postgres
用户的环境,命令行提示符通常会改变以表明当前用户身份。
3.2. 进入 PostgreSQL 交互环境
在 postgres
用户环境下,使用以下命令进入 PostgreSQL 的交互式 shell(psql
):
psql
此时,你会看到类似 postgres=#
的提示符,表明已成功进入 PostgreSQL 数据库管理系统。
3.3. 修改密码
在 psql
环境中,使用 ALTER USER
命令来修改 postgres
用户的密码。例如,要将密码设置为 newpassword
(请将 newpassword
替换为你实际想要设置的强密码),执行以下命令:
ALTER USER postgres WITH PASSWORD 'newpassword';
执行完上述 SQL 语句后,如果没有报错,说明密码修改成功。
3.4. 退出 PostgreSQL 交互环境和 postgres 用户
修改完密码后,输入以下命令退出 psql
交互环境:
\q
然后输入以下命令退出 postgres
用户,返回到原来的用户环境:
exit
3.5.增加www-data账户
sudo -u postgres createuser www-data
如果这步不执行,后面导入数据的时候会提示www-data账户不存在,详情参考5.2.2
3.6.修改postgresql.conf配置文件
默认是在:/etc/postgresql/14/main目录下:
sudo vim /etc/postgresql/14/main/postgresql.conf
按下面修改这些配置项即可。
shared_buffers = 2GB
work_mem = 50MB
maintenance_work_mem = 10GB
fsync = off
synchronous_commit= off
full_page_writes = off
checkpoint_timeout = 10min
checkpoint_completion_target = 0.9
effective_cache_size = 24GB
4.下载并编译Nominatim
4.1.下载Nominatim
下载地址:https://github.com/osm-search/Nominatim
找一个自己喜欢的版本下载
下载后拷贝到服务器,解压即可:例如我放在/opt目录下
#进入/opt目录
cd /opt
#我选择的是4.5.0版本,解压命令如下
unzip Nominatim-4.5.0.zip
进入解压后的目录:
cd Nominatim-4.5.0
4.2.编译Nominatim
在Nominatim-4.5.0目录下创建编译目录/build
mkdir /opt/Nominatim-4.5.0/build
cd /opt/Nominatim-4.5.0/build
然后执行命令:
cmake ..
这时候会提示 osm2pgsql是空的,需要下载osm2pgsql
点击这里可以跳转到下载地址
然后执行下载命令:
# 返回到Nominatim-4.5.0目录下
cd /opt/Nominatim-4.5.0
#下载
git clone --recursive https://github.com/osm2pgsql-dev/osm2pgsql.git
我们删除/build目录下之前编译生成的文件,再进行编译命令:
cd /build
cmake ..
缺少country_osm_grid.sql文件
按照提示执行下面的命令即可:
wget -O /opt/Nominatim-4.5.0/data/country_osm_grid.sql.gz https://www.nominatim.org/data/country_grid.sql.gz
再次清理之前的编译文件,重新编译:
cd /build
cmake ..
编译完毕,执行:make
make
最后执行下面命令完成Nominatim的编译
sudo make install
4.3.安装psycopg
Nominatim 通常使用 psycopg2
,可以按照以下命令进行安装:
pip install psycopg2-binary
但是我的环境使用的是psycopg3,可以使用命令:
pip install psycopg[binary]
如果这步不执行会出现5.2.1问题。
5.数据导入
5.1.执行导入
数据下载方式有两种,一种是在/opt/Nominatim-4.5.0/data目录下执行下载命令:
cd /opt/Nominatim-4.5.0/datawget https://planet.openstreetmap.org/pbf/planet-latest.osm.pbf
一种是下载后将文件拷贝到服务器中,建议这种,下载方式在1中已经说明。
在 /opt/Nominatim-4.5.0/data目录下执行命令
nominatim import --osm-file planet-latest.osm.pbf
如果我们导入的数据量非常庞大,而且控制台不希望一直开着查看输出的进度,那么我们可以将进度打印到日志文件,导入命令如下:
nominatim import --osm-file planet-latest.osm.pbf > nominatim_import.log 2>&1
正常情况下会开始导入数据导入
经历很长的一段时间后,可以看到数据导入成功的提示
这时候还没结束,还需要继续等待,过了几个小时后,会继续打印日志
5.2.异常
5.2.1.No module named 'psycopg'
给出的错误信息 ModuleNotFoundError: No module named 'psycopg'
可知,Python 解释器在运行时未能找到 psycopg
模块,而 psycopg
是用于与 PostgreSQL 数据库进行交互的库,可以使用 pip
来安装 psycopg
模块。psycopg
有两个主要版本,psycopg2
是传统版本,psycopg3
是新版本。
Nominatim 通常使用 psycopg2
,可以按照以下命令进行安装:
pip install psycopg2-binary
但是我的环境使用的是psycopg3,可以使用命令:
pip install psycopg[binary]
然后再执行导入命令:
nominatim import --osm-file planet-latest.osm.pbf
这里时候如果我们没有清理数据库会提示数据库已经存在
执行清理数据库的命令:
如果过程中执行失败,需要重新导入都需要先执行清理数据库的命令。
dropdb nominatim
5.2.2.www-data账户不存在
然后再执行一次导入命令:
nominatim import --osm-file planet-latest.osm.pbf
发现提示www-data账户不存在,需要创建。执行创建用户的命令:
sudo -u postgres createuser www-data
创建后再次清理数据库,执行导入操作,看到下面的进度说明我们导入开始,等待导入结束。这个是非常耗时的,确保服务器的稳定性。否则要重头再来。
5.2.3.内存不足,导致osm2pgsql意外中断
如果在导入过程中出现内存不足,导致osm2pgsql意外中断,则可以采用增加虚拟内存的方式进行临时解决,有条件的可以增加物理内存条。
Processing: Node(1004520k 357.2k/s) Way(0k 0.00k/s) Relation(0 0.0/s)Traceback (most recent call last):File "/usr/local/bin/nominatim", line 12, in <module>exit(cli.nominatim(module_dir='/usr/local/lib/nominatim/module',File "/usr/local/lib/nominatim/lib-python/nominatim_db/cli.py", line 260, in nominatimreturn get_set_parser().run(**kwargs)File "/usr/local/lib/nominatim/lib-python/nominatim_db/cli.py", line 122, in runret = args.command.run(args)File "/usr/local/lib/nominatim/lib-python/nominatim_db/clicmd/setup.py", line 86, in runreturn asyncio.run(self.async_run(args))File "/usr/lib/python3.10/asyncio/runners.py", line 44, in runreturn loop.run_until_complete(main)File "/usr/lib/python3.10/asyncio/base_events.py", line 649, in run_until_completereturn future.result()File "/usr/local/lib/nominatim/lib-python/nominatim_db/clicmd/setup.py", line 105, in async_runself._base_import(args)File "/usr/local/lib/nominatim/lib-python/nominatim_db/clicmd/setup.py", line 171, in _base_importdatabase_import.import_osm_data(files,File "/usr/local/lib/nominatim/lib-python/nominatim_db/tools/database_import.py", line 135, in import_osm_datarun_osm2pgsql(options)File "/usr/local/lib/nominatim/lib-python/nominatim_db/tools/exec_utils.py", line 77, in run_osm2pgsqlsubprocess.run(cmd, cwd=options.get('cwd', '.'),File "/usr/lib/python3.10/subprocess.py", line 526, in runraise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '[PosixPath('/usr/local/lib/nominatim/osm2pgsql'), '--create', '--slim', '--log-progress', 'true', '--number-processes', '1', '--cache', '10210', '--style', '/usr/local/etc/nominatim/import-extratags.lua', '--output', 'flex', 'planet-latest.osm.pbf']' died with <Signals.SIGKILL: 9>.
我采用的方法是增加虚拟内存:
(1)查看当前虚拟内存使用情况
使用命令free -h
可以查看当前系统的虚拟内存使用情况。
(2)创建新的交换文件
确定交换文件的大小和位置,例如创建一个 32GB 的交换文件在/swapfile
路径下,使用命令:
sudo fallocate -l 32G /swapfile
你可以根据实际需求调整大小
设置文件权限,确保只有 root 用户可以读写这个文件:
sudo chmod 600 /swapfile
将新文件设为交换文件:
sudo mkswap /swapfile
启用交换文件:
sudo swapon /swapfile
为了确保系统重启后虚拟内存仍然可用,需要将交换文件添加到/etc/fstab
文件中。打开该文件:
sudo vim /etc/fstab
在文件末尾添加以下行:
/swapfile none swap sw 0 0
(3)验证虚拟内存修改是否生效
使用命令:
free -h
查看虚拟内存是否已经成功修改并显示在Swap
列中。
一般来说,交换文件的大小可以根据物理内存的大小来确定。在过去,通常建议交换文件大小为物理内存的 1.5 到 2 倍。例如,如果系统有 4GB 的物理内存,那么交换文件可以设置为 6GB 到 8GB。然而,随着物理内存容量的不断增加,这个比例可以适当降低。对于现代系统,尤其是那些拥有 8GB 或更多物理内存的系统,交换文件大小可以设置为物理内存的 0.5 到 1 倍。
因为我的物理内存是32GB,所以我这里将交换文件也设置为32GB。
5.2.4."/var/run/postgresql/.s.PGSQL.5432" failed: 权限不够
connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: 权限不够
(1)编辑 postgresql.conf
文件
sudo vim /etc/postgresql/<版本号>/main/postgresql.conf
检查 listen_addresses
和 port
设置
listen_addresses = 'localhost' # 或者 listen_addresses = '*'
port = 5432
保存并退出文件。
(2)编辑 pg_hba.conf
文件
sudo vim /etc/postgresql/<版本号>/main/pg_hba.conf
确保有允许本地连接的配置项,例如:
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
这里的 trust
表示允许无密码连接,在生产环境中建议使用更安全的认证方式,如 md5
。
(3)重启 PostgreSQL 服务
sudo systemctl restart postgresql
5.3.导入完毕
经历长时间的等待(5天时间),终于将全球数据导入到了数据库,算上下载数据,整个过程需要10来天左右,真不易。
6.部署应用服务
6.1.安装apache2
sudo apt install -y apache2 libapache2-mod-php
6.2.创建一个web目录
mkdir /opt/nominatim-web
数据库导入完毕后会在data目录下自动生成一个website的目录,将website所有文件复制到/opt/nominatim-web
sudo cp -r /opt/Nominatim-4.5.0/data/website/ /opt/nominatim-web/
6.3.配置并启动nominatim web
在apache配置中为nominatim添加一个配置。
sudo tee /etc/apache2/conf-available/nominatim.conf << EOFAPACHECONF
<Directory "/opt/nominatim-web/website">Options FollowSymLinks MultiViewsAddType text/html .phpDirectoryIndex search.phpRequire all granted
</Directory>Alias /nominatim /opt/nominatim-web/website
EOFAPACHECONF
然后启用配置并重启 apache
sudo a2enconf nominatimsudo systemctl restart apache2
正常情况下,我们在浏览器输入:
http://你的IP地址/nominatim//reverse?format=jsonv2&accept-language=en&lat=22.56955&lon=120.651554
就可以返回下面的字符串:
{"place_id":193008953,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"way","osm_id":265424501,"lat":"22.56946435874501","lon":"120.65190743779885","place_rank":26,"category":"highway","type":"tertiary","importance":0.0533433333333333,"addresstype":"road","name":"佳興道路","display_name":"佳興道路, Taiwu Village, Taiwu, Pingtung County, 921, Taiwan","address":{"road":"佳興道路","city_district":"Taiwu Village","town":"Taiwu","county":"Pingtung County","ISO3166-2-lvl4":"TW-PIF","postcode":"921","country":"Taiwan","country_code":"tw"},"boundingbox":["22.566305","22.5732423","120.6493797","120.660727"]}
如图:
6.4.应用程序无法通过 Unix 域套接字连接到 PostgreSQL 服务器问题排查
浏览器访问解析地址时候,如果出现下面的问题,说明应用程序无法通过 Unix 域套接字连接到 PostgreSQL 服务器,通常是由于权限问题或服务未运行导致的。
确认 PostgreSQL 服务状态
sudo systemctl status postgresql
如果服务未运行:
sudo systemctl start postgresql
sudo systemctl enable postgresql # 开机自启
检查 Unix 域套接字文件权限
ls -la /var/run/postgresql/
正常输出示例
drwxrwxr-x 2 postgres postgres 80 May 13 15:30 .
drwxr-xr-x 13 root root 420 May 13 15:30 ..
srwxrwxrwx 1 postgres postgres 0 May 13 15:30 .s.PGSQL.5432
问题排查
- 如果目录或套接字文件不存在,可能是 PostgreSQL 未正确启动。
- 如果权限不是
srwxrwxrwx
,尝试:sudo chmod 777 /var/run/postgresql/
验证 PostgreSQL 配置
编辑 /etc/postgresql/14/main/postgresql.conf
:
sudo vim /etc/postgresql/14/main/postgresql.conf
确保以下配置正确:
unix_socket_directories = '/var/run/postgresql'
port = 5432
listen_addresses = 'localhost' # 或 '*' 允许远程访问
重启服务使配置生效:
sudo systemctl restart postgresql
添加用户到 postgres 组:
将当前用户(如 www-data
)添加到 postgres
组:
sudo usermod -aG postgres www-data
重新登录会话(或重启系统)使组变更生效。